榆树中的无穷大符号

时间:2016-06-20 13:09:43

标签: elm

在我与同事合作的项目中,我们使用了UrlParser模块,我们偶然发现了这个错误:

The type annotation for ourParser does not match its definition.

The type annotation is saying:

    UrlParser.Parser a a

But I am inferring that the definition has this type:

    UrlParser.Parser (String -> ∞) (String -> ∞)

Hint: A type annotation is too generic. You can probably just switch
to the type I inferred. These issues can be subtle though, so read 
more about it.

我们的代码就像

ourParser : UrlParser.Parser a a
ourParser =
    UrlParser.oneOf
        [ UrlParser.s "home"
        , UrlParser.s "detail" </> UrlParser.string
        ]

主要问题是:这个符号是什么?它在哪里定义?如果我尝试在我的函数定义中复制/粘贴它,我会收到语法错误,好像Elm实际上并不知道该字符是什么......

以下问题是:我的代码如何发生此类错误?

1 个答案:

答案 0 :(得分:5)

备选列表中的第二个解析器组合

UrlParser.s "detail" : Parser a a
UrlParser.string     : Parser (String -> b) b
使用

(</>) : Parser u v -> Parser v w -> Parser u w

正如您所希望看到的,以下类型必须匹配:

u ~ a
v ~ a
v ~ (String -> b)
w ~ b

结果类型是

UrlParser.s "detail" </> UrlParser.string  :  Parser (String -> b) b

备选列表中的第一个解析器类型为

UrlParser.s "home"  :  Parser c c

因为您正在构建这些列表,所以它们必须具有相同的常规类型。因此,c ~ (String -> b),还有c ~ b。你在这里有一个循环,导致无限类型。这就是无穷大符号的意思。

错误文本确实具有误导性,因为Elm的类型系统不支持无限类型(因为它们毫无意义)。这听起来像一个错误,因为Elm应该解释无限类型总是指向编程错误。

documentation for oneOf显示了如何通过使用format来组合不同类型的解析器。

在任何情况下,您都需要将第一个解析器转换为Parser (String -> c) c类型的解析器。从类型来看,将format "some string"应用于第一个解析器似乎已经足够了,但我对Elm或UrlParser的了解不足以对此提供任何保证。