Haskell运算符声明

时间:2015-03-03 22:02:05

标签: haskell

我试图从一本带练习的书中学习哈斯克尔。我无法通过这个,我不知道问题是什么。所以我要声明一个<<定义。在' a'与正确的除数相比,它的除数更少' b'有,应该是真的。像6<< 10,6有4个除数,10有2个适当的除数所以它应该是假的。我已经对除数和适当的除数进行了定义,但是当我试图使用它们时,它就不会发生。

    divisors :: Integer -> [Integer]
    divisors a = [n | n <- [1..a], a `mod` n == 0]

    properDivisors :: Integer -> [Integer]
    properDivisors a = [n | n <- [2..a `div` 2], a `mod` n == 0]

    (<<) :: Num a => a -> a -> Bool
    x << y = divisors x < properDivisors y

(<<) :: Num a => a -> a -> Bool已修复。

1 个答案:

答案 0 :(得分:3)

您的<<运营商需要Integral a => a -> a -> Bool类型,因为divmod都需要Integral,而不仅仅是Num。如果您无法使用Integral约束,那么您必须编写自己的divmod版本,这些版本适用于所有Num

如果您注释掉所有类型签名,则可以看到:

> :set +m
> let divisors a = [n | n <- [1..a], a `mod` n == 0]
|     properDivisors a = [n | n <- [2..a `div` 2], a `mod` n == 0]
|     x << y = divisors x < properDivisors y
divisors :: Integral t => t -> [t]
properDivisors :: Integral t => t -> [t]
(<<) :: Integral t => t -> t -> Bool

如果我们检查divisorsproperDivisors中使用的函数类型,我们会得到

> :t mod
mod :: Integral a => a -> a -> a
> :t div
div :: Integral a => a -> a -> a
> :t (==)
(==) :: Eq a => a -> a -> Bool
> :i Integral
class (Real a, Enum a) => Integral a where
    ...
> :i Real
class (Num a, Ord a) => Real a where
    ...
> :i Ord
class Eq a => Ord a where
    ...

(其他约束没有先决条件)所以为了使用moddiv,类型必须是NumEqOrdEnumRealIntegral,因为这是在Haskell中设置的类型类层次结构。适合这些约束的两种内置类型是IntInteger。由于FloatDouble未实现Integral,但他们确实实施了Num,因此您无法使用moddiv Num约束。