我正在尝试使用端口将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 -> Cmd msg
。我不明白msg
来自哪里,所以我去检查code,我仍然不明白这条线的含义。
msg
来自哪里? type Cmd msg = Cmd
是什么意思?提前谢谢。
答案 0 :(得分:9)
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
答案 1 :(得分:4)
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
答案 2 :(得分:1)
您的第一个编译错误是因为您的import
成功定义,但所需的格式是所有导入都在所有定义之前。
至于msg
中String -> Cmd msg
的含义,它只是一个类型变量 - Elm中类型注释中的所有小写类型名称都是类型变量,而以大写字母开头的那些是具体类型。因此它与String -> Cmd a
或String -> Cmd foo
相同。
在Elm中,与Haskell和其他一些函数式语言一样,如果类型变量在类型注释中,则隐式universally quantified。所以我们将上面的类型读作
changePage : ∀msg.String → Cmd msg
即,对于任何类型msg
,changePage
可以String
Cmd
msg
&#39;。
这意味着表达式changePage "myPage.html"
可以在您想要某种类型命令的代码中的任何位置使用。这似乎是有道理的,因为它代表了“"myPage.html"
发送给changePage
端口&#39;”的任何人的命令。