Elm的"type"语法-值从哪里来?

10

我是一个新手,目前正在学习Elm。我来自JS / React,并且没有任何RFP的经验。

我在这里的指南中: http://guide.elm-lang.org/architecture/user_input/text_fields.html

我遇到问题的部分是updateview

-- UPDATE

type Msg
  = Change String

update : Msg -> Model -> Model
update msg model =
  case msg of
    Change newContent ->
      { model | content = newContent }


-- VIEW

view : Model -> Html Msg
view model =
  div []
    [ input [ placeholder "Text to reverse", onInput Change ] []
    , div [] [ text (String.reverse model.content) ]
    ]

让我们从Msg声明开始。指南说:
它需要一个参数,这里是Change函数,在声明Msg类型时创建:
Change : String -> Msg
我不明白这里是怎么发生的:
type Msg
  = Change String

我们在这里如何定义一个Change函数?我们如何定义该函数的工作方式?对我来说,看起来我们只是声明了Msg的类型,其中包含一些Change以及String类型。

我的第二个问题是关于更新的:

update : Msg -> Model -> Model
update msg model =
  case msg of
    Change newContent ->
      { model | content = newContent }

对我来说,这似乎是一个高阶函数“update”,它接受一个“Msg”并返回一个函数“Model-> Model”。但是我们定义了一个带有两个参数的函数。那么“Msg-> Model-> Model”只是表示除最后一部分外都是参数吗?
然后我们调用“Change”函数:
Change newContent ->
          { model | content = newContent }

我不理解的是箭头。通常,箭头会在参数定义之后出现。但是,在这里,我们在->之前有一个函数的结果。

我希望我的问题有意义,我只是对这个(可能很棒的)语言感到非常困惑。

2个回答

6
当你声明 type Msg = Change String 时,你正在声明一个单一的类型 (Msg),它有一个构造函数可以接受一个字符串。
请参见 Elm 指南中关于 Union Types (也称为代数数据类型,ADT) 的部分。
以下是一个示例:
type User = Anonymous | Named String

So creating the type User also created constructors named Anonymous and Named. If you want to create a User you must use one of these two constructors

构造函数是一种函数,因此您可以像这样调用它们:Change "a string"(返回类型Msg)。
构造函数还提供了使用模式匹配从联合类型中提取内部值的能力。这就是您不熟悉的->的用法。
case msg of
  Change theString -> ... use theString ...

您的第二个问题;

对我来说,这看起来像是update是一个高阶函数,它接受一个Msg并返回一个函数Model -> Model

是的,这或多或少就是发生的事情。函数应用的优先级规则意味着您可以在没有括号的情况下调用它们。这称为柯里化,并且在elm指南中也有介绍。


3

为了更清楚地解释第二部分:

所有函数都是柯里化的,这意味着 update: Msg->Model->Model 可以接收一个 Msg 并返回一个函数 Model->Model,或者接收一个 Msg 和一个 Model 并返回一个 Model

实际上,当你调用 update aMessage aModel 时,你实际上调用的是 update aMessage,它会返回一个函数,然后你将 aModel 传递给该函数,该函数将运行函数体中的表达式并返回更新后的模型。

箭头只是 case.. of 语法的一部分。左侧是要匹配的模式,右侧是要执行的表达式。在你的例子中,只有使用 Change 构造函数创建的 Msg 才会执行 update 表达式。

type Msg
  = Change String | Delete

update : Msg -> Model -> Model
update msg model =
  case msg of
    Change newContent ->
      { model | content = newContent }
    Delete ->
      { model | content = "" }

在前一个情况下,Msg 可以使用 Change StringDelete 构建。根据 Msg 的构建方式,更新函数的行为会有所不同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接