【问题标题】:What does comparable mean in Elm?Elm 中的可比性是什么意思?
【发布时间】:2015-08-07 19:54:39
【问题描述】:

我无法理解 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 -&gt; Boolf2 还可以接受哪些其他可比对象?

【问题讨论】:

    标签: elm


    【解决方案1】:

    通常当您在 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 是一个具有内置特殊含义的类型变量。这意味着它只会匹配“可比较”类型,如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
    

    编辑:我为这个错误打开了issue

    【讨论】:

    【解决方案2】:

    比较任意两个可比较的值。可比较的值包括StringCharIntFloatTime,或listtuple包含可比较的值。这些也是唯一用作 Dict 键或 Set 成员的值。

    取自 elm 文档 here

    在旧版 Elm 中:

    可比较的类型包括numbers, characters, strings,~~ lists of comparable thingstuples of comparable things。注意 具有 7 个或更多元素的元组不可比较;为什么你的元组 这么大?

    这意味着:

    [(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

    注意:当人们尝试使用 联合类型 作为 DictKey 时,通常会遇到 comparable 类型的问题/strong>.

    联合类型的标签和构造函数不可比较所以以下内容甚至无法编译。

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

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

    【讨论】:

    • 您似乎阅读了我的问题的标题,但没有阅读完整内容。提出问题时我的困惑是因为编译器中存在错误。选择为正确的答案引用了该错误。 github.com/elm-lang/elm-compiler/issues/1013
    • @z5h 是的,在这方面你是对的。不过,我认为我的回答是相关的,因为这个问题是谷歌中出现的第一件事——一旦一个刚接触 elm 的人试图理解 comparable 是什么意思 .我的答案是给他们的——因为我自己花了 20 分钟来理解 这个可比性究竟是什么——我惊讶地发现 Bools 不被认为是可比的。选定的答案解释了:“Int、String 和其他一些” - 不是很具体。这就是我包含 elm-docs 片段的原因。
    • 这个答案已经过时了。该引用和链接指向旧版本的 elm-core(此处为新版本:package.elm-lang.org/packages/elm/core/latest/Basics#compare),并且 Elm 不能再拥有超过两个成员的元组。
    • @Charlie Elm can no longer have Tuples with more than two members - 这是什么意思? Elm 接受(1,2,3)。它不接受(1,2,3,4),它会强制您使用命名记录——这是个好主意。您仍然可以使用((1,2,3,), 4 ) 来解决它,但使用记录对所有相关人员来说要好得多,因为它不会在记住您想要的位置 3 和 4 的值时增加认知负担。我会更新答案。
    • 好收获!我的意思是“Elm 不能再拥有超过 三个 成员的元组”
    【解决方案3】:

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

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

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

    您会看到它实际上确实在可能的情况下将comparable 折叠为正确的类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-12
      • 2017-06-11
      • 2018-03-05
      • 2023-03-27
      相关资源
      最近更新 更多