Elm 中的 comparable 是什么意思?

What does comparable mean in Elm?

我无法理解 Elm 中的 comparable 到底是什么。 Elm 和我一样困惑。

关于 REPL:

> f1 = (<)
<function> : comparable -> comparable -> Bool

因此 f1 接受可比较对象。

> "a"
"a" : String
> f1 "a" "b"
True : Bool

看来String是可以比较的

> f2 = (<) 1
<function> : comparable -> Bool

所以f2接受一个可比较的。

> f2 "a"
As I infer the type of values flowing through your program, I see a conflict
between these two types:

    comparable

    String

那么String不是可比的吗?
为什么f2的类型不是number -> Boolf2 可以接受哪些其他比较对象?

我认为这个问题可能与有关。 IntString 都是 comparable,因为字符串可以与字符串进行比较,整数可以与整数进行比较。一个可以接受任何两个可比值的函数将有一个签名 comparable -> comparable -> ... 但在函数的任何一个评估中,两个可比值必须属于同一类型。

我认为上面 f2 令人困惑的原因是 1number 而不是具体类型(这似乎阻止了编译器识别可比较对象必须是某种类型的,可能应该是固定的)。如果你要这样做:

i = 4 // 2
f1 = (<) i   -- type Int -> Bool
f2 = (<) "a" -- type String -> Bool

您会看到它实际上 确实comparable 折叠为正确的类型。

通常情况下,当您在 Elm 的类型中看到类型变量时,该变量是不受约束的。当您随后提供特定类型的内容时,变量将被该特定类型替换:

-- says you have a function:
foo : a -> a -> a -> Int
-- then once you give an value with an actual type to foo, all occurences of `a` are replaced by that type:
value : Float
foo value : Float -> Float -> Int

comparable是一个具有内置特殊含义的类型变量。这意味着它只会匹配 "comparable" 类型,例如 IntString 和其他一些类型。但除此之外它应该表现相同。所以我认为类型系统中有一个小错误,因为你得到:

> f2 "a"
As I infer the type of values flowing through your program, I see a conflict
between these two types:

    comparable

    String

如果错误不存在,您将得到:

> f2 "a"
As I infer the type of values flowing through your program, I see a conflict
between these two types:

    Int

    String

编辑:我为这个 bug

打开了一个 issue

Compare any two comparable values. Comparable values include String, Char, Int, Float, Time, or a list or tuple containing comparable values. These are also the only values that work as Dict keys or Set members.

摘自榆树文档 here

在旧的 Elm 版本中:

Comparable types includes numbers, characters, strings,~~ lists of comparable things, and tuples of comparable things. Note that tuples with 7 or more elements are not comparable; why are your tuples so big?

这意味着:

[(1,"string"), (2, "another string")] : List (Int, String) -- is comparable

但是有

(1, "string",  True)` : (Int, String, Bool) -- or...

[(1,True), (2, False)] : List (Int, Bool ) -- are ***not comparable yet***. 

讨论了这个问题here

注意:通常人们在尝试使用 联合类型 作为 Key 时遇到 comparable 类型的问题在 Dict.

联合类型的标记和构造函数不可比较所以下面的甚至不能编译。

type SomeUnion = One | Two | Three
Dict.fromList [ (One, "one related"), (Two, "two related") ] : Dict SomeUnion String

通常当您尝试这样做时,您的数据结构会有更好的方法。但在决定之前 - 可以使用 AllDict