Skip to content

Instantly share code, notes, and snippets.

What would you like to do?

Scenario: Given a cookie string (which may be absent), parse and return a User record/struct

Often we'd write functions where arguments are "nullable", aka *string in Go, aka a Maybe in Elm

-- function `userFromCookie` with parameter type `Maybe String` return type `User`
userFromCookie1 : Maybe String -> User
userFromCookie1 maybeString =
    case maybeString of
        Nothing ->

        Just s ->

It's beneficial to write functions that simply work with "solid" values (the "not nullable" variant). One benefit is that my function bodies end up simpler

userFromCookie2 : String -> User
userFromCookie2 s =

"But if the argument value can indeed by absent, aka null or Nothing, we can't avoid managing that, right?" Yes, the tradeoff is that the call sites of those functions become more involved

  currentUser =
-     userFromCookie1 maybeCookieString
+     Maybe.withDefault Anonymous ( userFromCookie2 maybeCookieString)

Once you get used to seeing map, withDefault, andThen and notice the same patterns occur in other structures like Result, RemoteData, List, ...

call sites of those functions become more involved

you'll see there's a structure to this code increase (it isn't adhoc) and realise that when functions work with "solid" values parameters, the hit rate of reusing them goes up steeply -- the same function can just be slot into various context verbatim.

    userResult = userFromCookie2 stringReadFromIO
case userResult of
    Err err ->
        -- render IO error with variable `err`

    Ok user ->
        -- render `User` with variable `user`
cookieStrings : List String
cookieStrings =
    [ string1, string2, string3 ]

userList : List User
userList = userFromCookie2 cookieStrings

Whereas functions written in our earlier style, userFromCookie : Maybe String -> User, would be awkward to reuse

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment