我试图从一本带练习的书中学习哈斯克尔。我无法通过这个,我不知道问题是什么。所以我要声明一个<<定义。在' 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
已修复。
答案 0 :(得分:3)
您的<<
运营商需要Integral a => a -> a -> Bool
类型,因为div
和mod
都需要Integral
,而不仅仅是Num
。如果您无法使用Integral
约束,那么您必须编写自己的div
和mod
版本,这些版本适用于所有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
如果我们检查divisors
和properDivisors
中使用的函数类型,我们会得到
> :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
...
(其他约束没有先决条件)所以为了使用mod
和div
,类型必须是Num
,Eq
,Ord
, Enum
,Real
和Integral
,因为这是在Haskell中设置的类型类层次结构。适合这些约束的两种内置类型是Int
和Integer
。由于Float
和Double
未实现Integral
,但他们确实实施了Num
,因此您无法使用mod
或div
Num
约束。