Hacker News new | ask | show | jobs
by josevalim 1350 days ago
Hi, author here.

You do get a class of tests but I don't believe they are sufficient. For example, in the first article, we have this code:

    let contactFromEmail name emailStr =
        let emailOpt = EmailAddress.create emailStr
        // handle cases when email is valid or invalid
        match emailOpt with
        | Some email ->
            let emailContactInfo =
                {EmailAddress=email; IsEmailVerified=false}
            let contactInfo = EmailOnly emailContactInfo
            Some {Name=name; ContactInfo=contactInfo}
        | None -> None
While the types tell me that an email can be valid or not, and that the function may or may not return a contact, it does not tell me _which values_ will lead to those scenarios. The extrapolation is that this function could always return `None` and that would be alright from the point of view of types.

So perhaps you should still test that a valid email returns `Some contactInfo` and an invalid one returns `None`? Or maybe you have thoroughly unit tested `EmailAddress.create` and you feel confident in skipping tests here? Or perhaps you may want to test that `IsEmailVerified` is set to false (or maybe you even have logic that may set it to true in certain cases)?

In a nutshell, types would replace tests that assert on the states, but those are not the tests I write in the first place. The tests I write would rather focus which values give me certain states and assert which values inhabit those states.

1 comments

This code example doesn't make much sense. There is already a type to represent a valid email address (EmailAddress), why are we creating a function to make contacts that receives an email as a string. Just change the function to receive EmailAddress in the first place and avoid all the matching mess.
I agree,

You can /always/ go from `f : t -> r` to `f' : t option -> r option` with `Option.map` (ML-syntax, translate to w/e type syntax you're most familiar with), but the reverse is not true.

I think that the example is super-simplified though and I think that the central point still stands if you have multiple errors though.