0

elm n00b. I've read that Elm requires Maybes be handled explicitly. That said when dealing with nested Maybes, is there a way/pattern of expressing things to say "if all the Maybes contain values then do something, else give me this default"?

I'd think Maybe.andThen except I don't see how it would fit here.

The closest I've come to a similar question is in Haskell: Simplifying nested Maybe pattern matching

Sample code that can be run at try-elm follows. We model a "box", that may contain a playing "marble", that may have a number of "vanes" (or flutes) at its center. updateBox increments the number of vanes, if any (assume it updates other values not shown here, hence the name)

What I'm looking for is a succinct way to say: "if the marble exists, and if it has vanes, give me a new marble w/ incremented vanes; else give me back marble as-is".

(Please note this could be restructured to avoid the nested Maybe traversal, but that's not the question.)

Aside: IMO it feels odd to need to say Nothing -> Just marble below at the -- why do we need Just? comment. The code is already following the Just marble path, so shouldn't it follow that the marble at that point is already a Just marble?

import Html exposing (text)

main =
  text (toString (updateBox mybox))

type alias Box = 
  {marble: Maybe Marble}

type alias Marble = 
  {vanes: Maybe Int}

mybox = Box <| Just <| Marble <| Just 1

updateBox: Box -> Box
updateBox b =
  let
    updateMarble marble =
      case marble of
        Just marble ->
          case marble.vanes of
            Just vanes -> Just {marble | vanes = Just(vanes + 1)}
            Nothing -> Just marble -- why do we need Just?
        Nothing -> marble
  in
    {b | marble = updateMarble b.marble}
Community
  • 1
  • 1
pakx
  • 236
  • 1
  • 6
  • Fyi you don't need to pass through arguments to a function in a let block, you can access them directly if you want. `updateBox b = let updateMarble = case b.marble of ` – farmio Apr 13 '17 at 22:01

1 Answers1

2

You can use Maybe.map to eliminate the need for explicit Nothing checks:

updateBox: Box -> Box
updateBox b =
    {b | marble = Maybe.map (\m -> { m | vanes = Maybe.map ((+) 1) m.vanes }) b.marble}
Chad Gilbert
  • 36,115
  • 4
  • 89
  • 97