I am a huge fan of polymorphism and of accompanying static type checking. I find that, meta-programming aside, I mostly do not wish to write the kinds of things that are allowed by dynamic typing but disallowed by static typing. There are two exceptions, or blind spots to this and I thought I would detail the first one.
Suppose you have a data structure with several Maybe
fields:
1type alias Preferences =
2 { favouriteFood : Maybe Food
3 , favouriteBand : Maybe Band
4 , favouriteColor : Maybe Color
5 , favouriteNumber : Maybe Int
6 , favouriteName : Maybe String
7 }
Now suppose you want to count how many of these are set:
1numSetPreferences : Preferences -> Int
2numSetPreferences preferences =
3 [ preferences.favouriteFood
4 , preferences.favouriteBand
5 , preferences.favouriteColor
6 , preferences.favouriteNumber
7 , preferences.favouriteName
8 ]
9 |> List.count Maybe.isSomething
This is nice, but will not compile. The problem is that although the function Maybe.isSomething
has the type Maybe a -> Bool
so we don't really care what are in the Maybe
types of the list, you cannot write down the type of the list.
In this case you can get out of this, although it's definitely not as elegant:
1numSetPreferences : Preferences -> Int
2numSetPreferences preferences =
3 [ preferences.favouriteFood |> Maybe.isSomething
4 , preferences.favouriteBand |> Maybe.isSomething
5 , preferences.favouriteColor |> Maybe.isSomething
6 , preferences.favouriteNumber |> Maybe.isSomething
7 , preferences.favouriteName |> Maybe.isSomething
8 ]
9 |> List.count identity
This is a fairly minor irritation and I'm more than willing to live with this.