Search code examples
stringintelmoption-type

Elm 0.19 Maybe.withDefault


I have read the documentation, but i still don't understand how to Maybe.withDefault in my code. Because from a String.toInt I get Maybe Int, I cant use a + sign to add the values I try to convert into Integers. This is Elm 0.19. How can I fix this?

import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)


main =
  Browser.sandbox { init = init, update = update, view = view }


-- MODEL

type alias Model = {mainNum : String, curNum : String}

init : Model
init =
  {
      mainNum = ""
      ,curNum = ""
  }

-- UPDATE

type Msg = AddNum String | Add | Clear 

update : Msg -> Model -> Model
update msg model =
  case msg of
    AddNum number ->
        {model | curNum = model.curNum ++ number}

    Add ->
        {model | curNum = String.fromInt ((String.toInt model.curNum) + 
(String.toInt model.mainNum))}

    Clear ->
        init



-- VIEW

view : Model -> Html Msg
view model =
  div []
    [ div [] [ text  model.curNum]
    , button [ onClick (AddNum "1" )] [ text "1" ]
    , button [ onClick (AddNum "2" )] [ text "2" ]
    , button [ onClick (AddNum "3" )] [ text "3" ]
    , div [] []
    , button [ onClick (AddNum "4" )] [ text "4" ]
    , button [ onClick (AddNum "5" )] [ text "5" ]
    , button [ onClick (AddNum "6" )] [ text "6" ]
    , div [] []
    , button [ onClick (AddNum "7" )] [ text "7" ]
    , button [ onClick (AddNum "8" )] [ text "8" ]
    , button [ onClick (AddNum "9" )] [ text "9" ]
    , div [] []
    , button [ onClick (AddNum "0" )] [ text "0" ]
    , button [ onClick Clear] [ text "Clear" ]
    ]

Solution

  • withDefault : a -> Maybe a -> a
    

    This is a function received 2 params (the last one is the returned value).

    If a is an Int then we have:

    withDefault : Int -> Maybe Int -> Int
    
    -- if `a` is a `Float` then we have
    withDefault : Float -> Maybe Float -> Float
    
    -- in general, if `a` is an `X` then we have
    withDefault : X -> Maybe X -> X
    

    The 1st param is the one that will be returned once the 2nd param is Nothing.

    So if the 2nd param isn't Nothing then the function will return the value inside 2nd param.

    so basic example:

    -- hard-code 2nd param
    withDefault 10 (Just 20) -- this function call results 20
    withDefault 10 Nothing -- this function call results 10
    

    advanced ones:

    -- 2nd param is Nothing
    withDefault 10 (String.toInt "abc") -- this function call results 10
    
    -- 2nd param is not Nothing
    withDefault 10 (String.toInt "123") -- this function call results 123
    

    into your code:

    Add ->
        let
            cur : Int
            cur =
                Maybe.withDefault 0 (String.toInt model.curNum)
    
            main : Int
            main =
                Maybe.withDefault 0 (String.toInt model.mainNum)
         in
         { model | curNum = String.fromInt (cur + main) }
    

    As you can see, the Maybe.withDefault makes sure you always receive Int for your add returned Int calculation.

    Without it, you will always receive Maybe Int and the add of Maybe Int will always returns Maybe Int.

    Note: My code above is only for Maybe.withDefault usage explanation, not for production code