榆树"类型"语法 - 值来自哪里?

时间:2016-05-20 18:11:08

标签: syntax 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类型时创建:

     

更改:字符串 - >消息

我不知道这是怎么发生的:

type Msg
  = Change String

我们是如何在此定义更改功能的?我们如何定义该功能的工作原理?对我而言,我们只是声明了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 }

我不能到达那里的是箭头。通常箭头是在param定义之后。但是在这里我们得到了->之前的函数结果。

我希望我的问题有道理,我对这种(可能是很棒的)语言非常困惑。

2 个答案:

答案 0 :(得分:6)

当您声明type Msg = Change String时,您声明一个类型(Msg),其中一个构造函数接受一个字符串。

请参阅Union Types上的榆树指南部分(AKA代数数据类型,ADT)。

以下是一个示例:

type User = Anonymous | Named String
     

因此,创建类型User还会创建名为AnonymousNamed的构造函数。如果要创建User,则必须使用这两个构造函数之一

构造函数是函数,因此您可以将它们称为Change "a string"(返回类型Msg

构造函数还提供了使用模式匹配来提取联合类型中的内部值的功能。这是您不熟悉的->的使用。

case msg of
  Change theString -> ... use theString ...

你的第二个问题;

  

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

是的,这或多或少发生了什么。函数应用程序的优先规则意味着您可以不带括号调用它们。这称为 currying ,它也包含在榆树指南

答案 1 :(得分:3)

只是为了澄清第二部分:

所有功能都是curry,这意味着update: Msg->Model->Model可以收到Msg并返回功能Model->Model或接收MsgModel并返回Model

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

箭头只是case.. of语法的一部分。左侧是您要匹配的模式,右侧是您要执行的表达式。在您的情况下,只有在使用Change构造函数创建Msg时,更新才会执行表达式。

type Msg
  = Change String | Delete

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

在上一个案例中,可以使用Change StringDelete构建Msg。根据msg的构造方式,更新函数的行为会有所不同。