use*_*462 3 haskell compare typeclass
我有一个功能:
comp :: (Ord a) => a -> a -> Bool
comp a b = if a > b then True else False
Run Code Online (Sandbox Code Playgroud)
这有效.但如果我这样做:
comp :: (Num a) => Int -> a -> Bool
comp a b = if a > b then True else False
Run Code Online (Sandbox Code Playgroud)
或这个:
comp :: (Ord a) => Int -> a -> Bool
comp a b = if a > b then True else False
Run Code Online (Sandbox Code Playgroud)
我收到一条错误消息:
无法演绎(a~Int)
咦?Num和Ord不包括Int吗?Num和Ord不仅仅包括实数而不是复数吗?
为什么在解释器中我可以比较任何真实到任何int:
4 > 4.5
False
Run Code Online (Sandbox Code Playgroud)
但我不允许定义一个将Ints与Nums或Ords进行比较的函数?
Ben*_*son 11
>期望两个Ord相同类型的实例.
ghci> :t (>)
(>) :: Ord a => a -> a -> Bool
Run Code Online (Sandbox Code Playgroud)
那种类型的签名不一样(Ord a, Ord b) => a -> b -> Bool,它可以是一个可以比较任何两个实例的函数的签名Ord.(不存在这种功能的非平凡版本.)
>对穷人程序员提出如此严格要求的原因是不同类型可能具有不同的排序语义.你会如何比较Int一个[Bool]?*尽管它们都是实例Ord,但比较它们没有意义,编译器也不会允许它:
ghci> 3 > [True, True, False]
<interactive>:6:1:
No instance for (Num [Bool]) arising from the literal `3'
Possible fix: add an instance declaration for (Num [Bool])
In the first argument of `(>)', namely `3'
In the expression: 3 > [True, True, False]
In an equation for `it': it = 3 > [True, True, False]
Run Code Online (Sandbox Code Playgroud)
每个实例都Ord定义了自己的版本>.这就是为什么你不能比较Int一个Float:
ghci> (3 :: Int) > (4 :: Float)
<interactive>:4:15:
Couldn't match expected type `Int' with actual type `Float'
In the second argument of `(>)', namely `(4 :: Float)'
In the expression: (3 :: Int) > (4 :: Float)
In an equation for `it': it = (3 :: Int) > (4 :: Float)
Run Code Online (Sandbox Code Playgroud)
*为了迂腐,你可以设计一些表示二进制整数的方法作为布尔列表.这样的表示对于newtype具有自己的Num和的实例是一个很好的候选者Ord.
原因4 > 4.5是文字4是多态的.它可以代表任何数字类型的'4'值:
ghci> :t 4
4 :: Num a => a
Run Code Online (Sandbox Code Playgroud)
同样,4.5可以采用任何小数类型(4.5 :: Fractional a => a).编译器足够聪明,可以意识到您正在将"任意数字"类型的值与"任何小数"类型的值进行比较,并使用最方便的具体类型,在本例中为Double.(Double被声明为default在标准的前奏.)因此,在表达4 > 4.5,4并且4.5都将是Double秒.
您可以Ord通过向其中一个操作数提供类型签名来强制比较使用特定具体类型的实例.