【问题标题】:What is the meaning of `Cmd msg`?`Cmd msg` 是什么意思?
【发布时间】:2016-12-23 19:42:59
【问题描述】:

我正在尝试使用端口将 URL 传递给 Javascript,以便将用户重定向到另一个页面。我写了一个port module 来包含我的项目所需的所有端口:

port module Utils exposing (..)
port changePage : String -> Cmd Event

然后,我将它导入到我的 Elm 文件中:

type Event = PageChange String
import Utils exposing (changePage)

但编译器不喜欢它:

It looks like the keyword `import` is being used as a variable.
8| import Utils exposing (changePage)
         ^
Rename it to something else.

所以我将端口定义移动到主文件:

type Event = PageChange String
port changePage : String -> Cmd Event

但是编译器还是不同意:

Port `changePage` has an invalid type.
28| port changePage : String -> Cmd Event
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You are saying it should be:
 String -> Platform.Cmd.Cmd BmC.Index.Event
But you need to use the particular format described here:
<http://guide.elm-lang.org/interop/javascript.html#ports>

所以我去看了那个特殊的格式,port check : String -&gt; Cmd msg。我不明白msg是从哪里来的,所以我去查了code,还是不明白那行是什么意思。

msg 来自哪里? type Cmd msg = Cmd 是什么意思?提前致谢。

【问题讨论】:

  • 看看example 我为类似的问题所做的。在出端口Cmd msg类型只表示它是一个命令,因为出端口不发送任何消息,你应该省略消息。
  • 谢谢!它解决了我的问题。但没有回答我的问题。

标签: elm elm-architecture


【解决方案1】:

import 语句必须出现在任何函数或类型定义之前。这就是您在此代码上遇到编译错误的原因:

type Event = PageChange String
import Utils exposing (changePage)

关于端口的问题:Elm 的端口是架构边缘的一项功能。它们允许与不同的语言进行互操作,因此,无论出于何种目的和目的,幕后都在发生着一些神奇的事情。

其他语言具有与其他语言互操作的类似“神奇”构造。 Haskell 有Foreign Function Interface (FFI),C# 有extern 关键字来调用外部库。

Cmd 的定义是那些通过查看代码并没有真正意义的部分之一。

type Cmd msg = Cmd

这并不能告诉我们太多,但没关系。它更像是编译器在编译时填充的占位符。其他语言也这样做。 Haskell often uses a bottom call of let x = x in x 表示编译器将实际实现的函数。

所以,除非你真的对 Elm 和 Javascript 之间的交叉实现感兴趣,否则没关系,你可以尽情想象并接受魔法。

至于能够在您的端口中指定具体类型,这只是编译器团队的另一种选择。尽管Cmd Event 是唯一可以通过端口的东西,但他们选择强制使用泛型类型作为 Cmd 的类型参数。 Cmd msg 的准确拼写不是必需的。 msg 可以是任何小写:

port check : String -> Cmd a

【讨论】:

    【解决方案2】:

    Elm 中的端口声明设计需要非常具体的类型定义注释。

    首先,我建议您查看Reading Types,尤其是在提到类型变量

    的段落中

    之后,请确保您熟悉Generic Data Structures,如果官方指南没有帮助,您可以查看我对类似问题的回答Understanding generic union types in Elm

    端口有点混乱,所以我打开了一个问题The guide on JavaScript interop should explain port function type definitions

    输出端口

    port out : String    ->    Cmd msg
                  |                 |
                  |                 |
              Concrete type    Generic type
              of outgoing      with `msg` type variable
              data             
                               Outgoing port never sends messages,
                               but you need to specify the type so the
                               compiler can infer, that you can use
                               this command to send the outgoing values
                               in any module, that imports "out" function
    

    传入端口

    port in : (List String -> msg)    ->    Sub msg
                         |                     |
                         |                     |
             A function, that accepts       Has to be generic,
             outgoing data and returns      because it is going to be
             a message. This function       a subscription with the
             is called "tagger"             same type as "tagger" returns
    
             Has to be generic, i.e. use
             `msg` type variable
    

    【讨论】:

      【解决方案3】:

      您的第一个编译器错误是因为您的 import 定义成功,但所需的格式是所有导入都在所有定义之前。

      至于String -&gt; Cmd msg中的msg是什么意思,它只是一个类型变量——Elm中类型注解中的所有小写类型名称都是类型变量,而以大写字母开头的是具体类型。所以和String -&gt; Cmd a或者String -&gt; Cmd foo是一样的。

      在 Elm 中,就像在 Haskell 和其他一些函数式语言中一样,如果类型变量在类型注释中,则它隐式为 universally quantified。所以我们把上面的类型读为

      changePage : ∀msg.String → Cmd msg
      

      也就是说,'对于任何类型的msgchangePage 可以将String 转换为Cmdmsg'。

      这意味着表达式changePage "myPage.html" 可以在代码中任何需要某种类型命令的地方使用。这似乎是有道理的,因为它代表了“请将"myPage.html" 发送给订阅changePage 端口的任何人”的命令。

      【讨论】:

        猜你喜欢
        • 2011-09-29
        • 2010-10-05
        • 2018-12-17
        • 2013-08-06
        • 2015-06-27
        • 1970-01-01
        • 1970-01-01
        • 2023-03-25
        • 1970-01-01
        相关资源
        最近更新 更多