Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Working with Maybe

Working with Maybe

View the live presentation: https://www.youtube.com/watch?v=43eM4kNbb6c

One of the selling points of Elm is that you cannot get null errors. Maybe is what allows Elm to avoid this billion-dollar problem entirely. It’s a beautiful solution.

But it doesn’t take too long before your code is one long ugly nested case statement checking Maybes at every level. Surely this can’t be right. There must be a better way.

We have an array of tools at our disposal to solve this problem, from simple convenience functions all the way to eliminating Maybe altogether in favor of other constructs. Join me on a whirlwind tour of these solutions and take back control of your codebase.

Joël Quenneville

July 06, 2018
Tweet

More Decks by Joël Quenneville

Other Decks in Technology

Transcript

  1. > All names lowercase > Vowel names prefixed with asterisk

    > Display unknown donors as "Anonymous"
  2. JAVASCRIPT let displayName = function(user) { if (startsWithVowel(user.name)) { "*"

    + user.name.toLowerCase(); } else { user.name.toLowerCase(); } }
  3. UNCERTAINTY let user1 = null; let user2 = { name:

    null }; displayName(user1); displayName(user2);
  4. UNCERTAINTY PROBLEMS 1. any value can be missing at any

    time 2. Maybe is viral 3. Programmers abuse the concept
  5. type alias User = { name : Maybe String }

    formatName : Maybe User -> Maybe String formatName maybeUser = case maybesUser of Just user -> case startsWithVowel user.name of Just True -> case user.name of Just name -> Just <| "*" ++ String.toLower name Nothing -> Nothing -- should never happen Just False -> case user.name of Just name -> Just <| String.toLower name Nothing -> Nothing -- should never happen Nothing -> Just "Anonymous" startsWithVowel : Maybe String -> Maybe Bool startsWithVowel name = -- ...
  6. !!!

  7. UNWRAPPING EARLY getNameOrDefault : Maybe User -> String getNameOrDefault optionalUser

    = case optionalUser of Just user -> user.name Nothing -> ""
  8. ANOTHER FORM OF OPTIONAL viewName : Maybe User -> Html

    a viewName optionalUser = case getNameOrDefault optionalUser of "" -> text "Anonymous" actualName -> text actualName
  9. EXPLICIT OPTIONAL VALUE viewName : Maybe User -> Html a

    viewName optionalUser = case optionalUser of Nothing -> text "Anonymous" Just user -> text user.name
  10. CONFIDENT BUSINESS FUNCTION formatName : User -> String formatName user

    = user.name |> String.toLower |> prefixVowelName
  11. BUSINESS FUNCTION WITH NO MAYBES userWithDonation : User -> Int

    -> String userWithDonation user donation = (formatName user) ++ " - $" ++ toString donation
  12. Write confident business-logic functions and only deal with Maybe at

    the edges of your system (with the appropriate map function)
  13. findByName : String -> List User -> Maybe User findByName

    name users = users |> List.filter (\user -> user.name == name) |> List.head
  14. GUIDELINE 2 Business functions may return Maybe but may not

    accept Maybe as any of its arguments.
  15. type alias Session = { searchTerm : Maybe String }

    session.searchTerm |> Maybe.andThen (\name -> findByName name users)
  16. UNCERTAINTY FROM WITHIN type alias DonorWizard = { donor :

    Maybe Donor , donationAmount : Maybe Int }
  17. UNION TYPES type DonorWizard = Step1 (Maybe Donor) | Step2

    Donor (Maybe Int) | Complete Donor Int
  18. > Actively try to model your data structures to avoid

    Maybe > Separate code that checks for presence from code that calculates values. > Business functions may return Maybe but may not accept Maybe as any of its arguments.
  19. JOËL QUENNEVILLE > Github - github.com/JoelQ > Slack - @joelq

    > Twitter - @joelquen Come talk to me, I have postcards!