榆木 0.19 Maybe.withDefault

Elm 0.19 Maybe.withDefault

我已经阅读了文档,但我仍然不明白如何在我的代码中 Maybe.withDefault。因为从 String.toInt 我得到了 Maybe Int,所以我不能使用 + 号来添加我尝试转换为整数的值。这是 Elm 0.19。我该如何解决这个问题?

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" ]
    ]

您确实需要带有 text 的字符串,但您的 onClicks 可以处理采用 Ints 的消息。即

button [ onClick (AddNum 7)] [ text "7" ]

我建议您也更改您的模型以使用整数,这样您就不必进行任何转换 from/to 字符串

我已经通过创建一个转换 Maybe Int -> Int 的函数修复了这个错误:

checkInt : Maybe Int -> Int
checkInt x = case x of
    Just y -> y
    Nothing -> 0
withDefault : a -> Maybe a -> a

这是一个接收 2 个参数的函数(最后一个是 returned 值)。

如果 a 是一个 Int 那么我们有:

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

一旦第二个参数Nothing第一个参数将被return编辑.

因此,如果 第二个参数 不是 Nothing 那么该函数将 return 第二个参数 [=50] 中的值=].

如此基本的例子:

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

高级:

-- 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

进入您的代码:

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) }

如您所见,Maybe.withDefault 可确保您在 add returned Int 计算中始终收到 Int

没有它,您将始终收到 Maybe Int 并且 Maybe Int 的添加将始终 returns Maybe Int.

注意: 我上面的代码仅用于Maybe.withDefault用法解释,不适用于生产代码

关于您的问题:

  1. String.fromIntreturnsMaybe Int,表示值可以是Just IntNothing
  2. 你不能只添加例如Just 1Nothing 在一起,甚至 Just 1Just 2
  3. 您需要以某种方式从 Just 1 中提取数字,或者如果它是 Nothing 则指定默认值(例如 0)。
  4. 这就是 Maybe.withDefault 派上用场的地方。它可以从任何 Maybe Int 中提取 Int(无论是 Nothing 还是 Just)。它需要 2 个参数:

    • first 是当第二个参数为 Nothing
    • 时使用的默认值
    • 第二个是实际的 Maybe

所以在你的代码中你可以像这样使用它:

{model 
  | curNum = 
      String.fromInt <|
        (Maybe.withDefault 0 <| String.toInt model.curNum) 
        + (Maybe.withDefault 0 <| String.toInt model.mainNum)
}

说了这么多,您可以通过在模型中使用 Int 并在视图中使用 String.fromInt 来省去所有麻烦。