【问题标题】:Haskell, multiple type classes for one argumentHaskell,一个参数的多个类型类
【发布时间】:2017-04-10 08:31:09
【问题描述】:

这是 Learn You A Haskell 中关于高阶函数的章节中的一个示例:

compareWithHundred :: (Num a, Ord a) => a -> Ordering  
compareWithHundred x = compare 100 x  

虽然函数的概念对我来说很清楚,但我不确定为什么类型签名是 (Num a, Ord a)。我们只传递要与 Int 类型的函数进行比较的整数。 Ord 在这里代表什么,为什么在类型签名中隐式传递参数?

【问题讨论】:

    标签: haskell types


    【解决方案1】:

    这不是此签名唯一可能的签名。它恰好是最通用的compareWithHundred :: Int -> Ordering 实际上是一个可能的实例化 - 多态 a 参数可以用任何可排序的数字类型进行实例化,这确实包括 Int,但也包括 IntegerRationalDouble...

    Prelude> let compareWithHundred :: (Num a, Ord a) => a -> Ordering; compareWithHundred x = compare 100 x
    Prelude> compareWithHundred (99 :: Int)
    GT
    Prelude> compareWithHundred (100.3 :: Double)
    LT
    

    并非所有数字类型都允许您对它们进行排序-比较——这是不可能的经典示例是复数(您可以对它们进行排序的“多个方向”) .

    Prelude Data.Complex> compareWithHundred (100 :+ 30 :: Complex Double)
    
    <interactive>:10:1:
        No instance for (Ord (Complex Double))
          arising from a use of ‘compareWithHundred’
        In the expression: compareWithHundred (100 :+ 30 :: Complex Double)
        In an equation for ‘it’:
            it = compareWithHundred (100 :+ 30 :: Complex Double)
    

    因此,您需要要求参数是一个数字(因此存在一个值 100 可以与之比较)并且参数在 Ord 类中。这个组合约束写成(Num a, Ord a)

    【讨论】:

      【解决方案2】:

      我有话要补充,以防你无法从 leftaroundabout 的详尽回答中收集到一些东西。

      类型签名中=&gt; 左侧的所有内容都是约束。像这样读取类型:

      compareWithHundred :: (Num a, Ord a) => a -> Ordering
                            ^^^^^^^^^^^^^^    ^    ^^^^^^^^
                             constraints      |         |
                                       argument type    |
                                                   result type
      

      所以你只向函数传递了一个参数,因为类型签名中只有一个参数aa 是一个类型变量,可以替换为任何类型只要该类型满足约束

      Num a 表示无论您用什么替换 a 都必须是数字(所以它可以是 IntIntegerDouble、...),而 Ord a 表示它必须具有可比性。 leftroundabout 的回答更详细地说明了为什么你需要两者,我只是想确保你知道如何阅读签名。

      所以在某种意义上说compareWithHundred "foobar" 是完全合法的,类型检查器说该表达式的类型是Ordering,但是稍后它会在尝试检查是否存在Num String 实例时失败。

      我希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-07
        • 2017-04-11
        • 1970-01-01
        • 1970-01-01
        • 2020-08-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多