Elm Language Special Type Variables


Elm defines the following special type variables that have a particular meaning to the compiler:

  • comparable: Comprised of Int, Float, Char, String and tuples thereof. This allows the use of the < and > operators.

    Example: You could define a function to find the smallest and largest elements in a list (extent). You think what type signature to write. On one hand, you could write extentInt : List Int -> Maybe (Int, Int) and extentChar : List Char -> Maybe (Char, Char) and another for Float and String. The implementation of these would be the same:

    extentInt list =
        helper x (minimum, maximum) = 
          ((min minimum x), (max maximum x))
        case list of 
          [] ->
          x :: xs ->
            Just <| List.foldr helper (x, x) xs

    You might be tempted to simply write extent : List a -> Maybe (a, a), but the compiler will not let you do this, because the functions min and max are not defined for these types (NB: these are just simple wrappers around the < operator mentioned above). You can solve this by defining extent : List comparable -> Maybe (comparable, comparable). This allows your solution to be polymorphic, which just means that it will work for more than one type.

  • number: Comprised of Int and Float. Allows the use of arithmetic operators except division. You can then define for example sum : List number -> number and have it work for both ints and floats.

  • appendable: Comprised of String, List. Allows the use of the ++ operator.

  • compappend: This sometimes appears, but is an implementation detail of the compiler. Currently this can't be used in your own programs, but is sometimes mentioned.

Note that in a type annotation like this: number -> number -> number these all refer to the same type, so passing in Int -> Float -> Int would be a type error. You can solve this by adding a suffix to the type variable name: number -> number' -> number'' would then compile fine.

There is no official name for these, they are sometimes called:

  • Special Type Variables
  • Typeclass-like Type Variables
  • Pseudo-typeclasses

This is because they work like Haskell's Type Classes, but without the ability for the user to define these.