Write Simple Validation Functions Using Elm's Result Type

    Enrico BuonannoEnrico Buonanno

    We start by writing some validation functions that use Elm's Result type to represent successful or failed validation. If you are unfamiliar with or need a refresher on the Result type, watch this lesson first.



    Become a Member to view code

    You must be a Member to view code


    Become a Member
    and unlock code for this lesson


    Instructor: 00:02 The way you represent an operation that can fail in Elm is with the result type. For instance, if I open the REPL and look at the signature of the string to int function, this is a function that takes a string and returns a result.

    00:20 The result is parameterized by string, meaning that if the conversion fails, we would get a string error message, and int, which is the payload, in case the conversion is successful.

    00:32 If you've seen my course on the Elm type system, you may remember a function with the same structure which validates an email address. It takes a string, and in case of failure, returns a string error message, and otherwise, wraps the string in a strongly typed address.

    00:49 Next, I'm going to create a file called validation.elm. This is where I will write my validation code. Let me call this module validation. For now, let me expose all the members.

    01:03 I'll start by writing some simple functions that validate that my data is correct. I'll write the function isNotEmpty that takes a string and returns a result, string string. Implementation is straightforward. If the value is an empty string, then I return an error saying, "This field is required." Otherwise, I return an OK wrapping the value.

    01:43 To make a couple of more examples, let me also write isEmail. This has the same signature as above. I'm going to perform a very simple check. I'm going to say that if the value contains an @, then it's OK. I'm going to wrap the value, and otherwise, "Please enter a valid email address."

    02:22 To show how we can deal with a different type, let's say isInt. In this case, the signature will be string to result string int. In this case, I will just reuse string.toInt. Notice the pattern. We always take in a value, in this case, is always a string, and returning a result, potentially performing a type conversion in the process.

    02:51 Let me capture this in an abstraction. I'm going to create a type alias validator. I'm going to say the validator takes a value of type A, it has a generic parameter A, and it returns a result of string -- that's the potential error -- or another type, B. I also have a generic parameter, B.

    03:17 In the case of the int function, A is string, and B is int. I can rewrite the signatures, isNotEmpty is a validator string string, and the same is 1 of isEmail. isInt is a validator string int, because we're going from string to int.

    03:37 Let me compile this. I have a little compilation error, because this needs to be exposing. Also, here I forgot to wrap this into an error.