Elm 中 'HTML msg' 中的 'msg' 实际上是什么?
What is the 'msg' in 'HTML msg' in Elm actually?
我正在自学 elm 并看到(当然)许多对 Html msg
--
的引用
我知道这是一个 'parameterised type',也就是说(据我了解),Html
类型的构造函数接受一个参数——与 List Char
差不多
好的。但是在接下来的一些教程中,我看到他们很快将 msg
更改为自定义类型,通常是这样的(我凭记忆这样做,所以请原谅我):
Html Msg
其中 Msg
可能定义为
type Msg =
Something | SomethingElse
我在这里也看到了 -- https://discourse.elm-lang.org/t/html-msg-vs-html-msg/2758 -- 他们说
The lower case msg is called a type variable. The upper case Msg is called a concrete type - its something your application has defined.
这部分回答了我的问题,但有人可以详细说明这到底是什么意思吗?因为当我看到像List String
这样的东西时,我明白String
在这个上下文中是什么意思,但是我不明白msg
在Html msg
中是什么意思。
此外,我们不是在更改函数的 return 值的类型吗?也就是说,如果 Elm 运行时期望 view
到 return 某个类型,并且该类型是 Html msg
,如果我们将 return 类型更改为 Html Whatever
,为什么会这样? (例如,我们不能将函数的 return 值从 List String
任意更改为 List Number
,对吗?)
来自 OOP 和 C、TypeScript 等类型化语言的背景,我认为任何 Msg
都需要以某种方式与 msg
相关,即 'extend' 它以某种方式允许多态性。显然我的看法是错误的,如有任何解释,我们将不胜感激!
tl;dr:只要每个函数都同意 msg
和 model
的类型,它们可以是任何你想要的。
就像List
的类型参数一样,msg
可以是任何东西。没有限制。为了演示,这是经典的 increment/decrement 示例,其中 msg
只是一个 Int
:
-- These type aliases aren't needed, but makes it easier to distinguish
-- their roles in later type signatures
type alias Model = Int
type alias Msg = Int
update : Msg -> Model -> Model
update msg model =
model + msg
view : Model -> Html Msg
view model =
div []
[ button [ onClick 1 ] [ text "+1" ]
, div [] [ text <| String.fromInt model.count ]
, button [ onClick (-1) ] [ text "-1" ]
]
main : Program () Model Msg
main =
Browser.sandbox { init = 0, view = view, update = update }
那么它是如何工作的呢?关键在于 Browser.sandbox
函数,因为它将所有内容连接在一起。它的类型签名是:
sandbox :
{ init : model
, view : model -> Html msg
, update : msg -> model -> model
}
-> Program () model msg
其中 model
和 msg
是类型变量。这两个都可以用任何具体类型替换,只要它符合此签名中给出的约束,即它们在 init
、view
和 [=24 中必须相同=] 函数。否则我们会在这里得到一个类型错误。例如,如果 update
需要 String
而不是 Int
,我们将得到错误:
This argument is a record of type:
{ init : Model, update : String -> Model -> Model, view : Model -> Html Msg
}
But `sandbox` needs the 1st argument to be:
{ init : Model
, update : String -> Model -> Model
, view : Model -> Html String
}
当然也不知道是对还是错,就是不匹配。但为了提供帮助,它假设 String
是正确的,并期望 view
到 return Html String
相反。
我希望这足以回答您的问题。如果没有,请评论并订阅!
你的问题的答案最好用例子来说明。
简短的说明:
我有一个这样的圣诞功能:
wrapPresents : presents -> String
但是类型是什么,presents
?它可以是任何你想要的!您可以将其替换为您自己的 'concrete type'。 presents
只是一个占位符!
wrapPresents : Boxes -> String wrapPresents boxes = "All the boxes are now wrapped!"
总结:msg(小写)只是一个占位符
我正在自学 elm 并看到(当然)许多对 Html msg
--
我知道这是一个 'parameterised type',也就是说(据我了解),Html
类型的构造函数接受一个参数——与 List Char
差不多
好的。但是在接下来的一些教程中,我看到他们很快将 msg
更改为自定义类型,通常是这样的(我凭记忆这样做,所以请原谅我):
Html Msg
其中 Msg
可能定义为
type Msg =
Something | SomethingElse
我在这里也看到了 -- https://discourse.elm-lang.org/t/html-msg-vs-html-msg/2758 -- 他们说
The lower case msg is called a type variable. The upper case Msg is called a concrete type - its something your application has defined.
这部分回答了我的问题,但有人可以详细说明这到底是什么意思吗?因为当我看到像List String
这样的东西时,我明白String
在这个上下文中是什么意思,但是我不明白msg
在Html msg
中是什么意思。
此外,我们不是在更改函数的 return 值的类型吗?也就是说,如果 Elm 运行时期望 view
到 return 某个类型,并且该类型是 Html msg
,如果我们将 return 类型更改为 Html Whatever
,为什么会这样? (例如,我们不能将函数的 return 值从 List String
任意更改为 List Number
,对吗?)
来自 OOP 和 C、TypeScript 等类型化语言的背景,我认为任何 Msg
都需要以某种方式与 msg
相关,即 'extend' 它以某种方式允许多态性。显然我的看法是错误的,如有任何解释,我们将不胜感激!
tl;dr:只要每个函数都同意 msg
和 model
的类型,它们可以是任何你想要的。
就像List
的类型参数一样,msg
可以是任何东西。没有限制。为了演示,这是经典的 increment/decrement 示例,其中 msg
只是一个 Int
:
-- These type aliases aren't needed, but makes it easier to distinguish
-- their roles in later type signatures
type alias Model = Int
type alias Msg = Int
update : Msg -> Model -> Model
update msg model =
model + msg
view : Model -> Html Msg
view model =
div []
[ button [ onClick 1 ] [ text "+1" ]
, div [] [ text <| String.fromInt model.count ]
, button [ onClick (-1) ] [ text "-1" ]
]
main : Program () Model Msg
main =
Browser.sandbox { init = 0, view = view, update = update }
那么它是如何工作的呢?关键在于 Browser.sandbox
函数,因为它将所有内容连接在一起。它的类型签名是:
sandbox :
{ init : model
, view : model -> Html msg
, update : msg -> model -> model
}
-> Program () model msg
其中 model
和 msg
是类型变量。这两个都可以用任何具体类型替换,只要它符合此签名中给出的约束,即它们在 init
、view
和 [=24 中必须相同=] 函数。否则我们会在这里得到一个类型错误。例如,如果 update
需要 String
而不是 Int
,我们将得到错误:
This argument is a record of type:
{ init : Model, update : String -> Model -> Model, view : Model -> Html Msg
}
But `sandbox` needs the 1st argument to be:
{ init : Model
, update : String -> Model -> Model
, view : Model -> Html String
}
当然也不知道是对还是错,就是不匹配。但为了提供帮助,它假设 String
是正确的,并期望 view
到 return Html String
相反。
我希望这足以回答您的问题。如果没有,请评论并订阅!
你的问题的答案最好用例子来说明。
简短的说明:
我有一个这样的圣诞功能:
wrapPresents : presents -> String
但是类型是什么,presents
?它可以是任何你想要的!您可以将其替换为您自己的 'concrete type'。 presents
只是一个占位符!
wrapPresents : Boxes -> String wrapPresents boxes = "All the boxes are now wrapped!"