Haskell 运算符声明
Haskell operator declaration
我正在尝试通过带练习的书学习 haskell。我无法通过这个,我不知道是什么问题。所以我要声明一个 << 定义。在 'a' 的除数少于适当的除数 'b' 的情况下,它应该是正确的。就像 6 << 10,6 有 4 个除数,10 有 2 个真除数,所以它应该是 False。我已经为除数和适当的除数做了一个定义,但是当我试图使用它们时,它不会发生。
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
已修复
您的 <<
运算符需要类型 Integral a => a -> a -> Bool
,因为 div
和 mod
都需要 Integral
,而不仅仅是 Num
.如果你不能使用 Integral
约束,那么你将不得不编写自己的 div
和 mod
版本,它们适用于所有 Num
s.
如果你注释掉所有的类型签名就可以看到:
> :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
约束。
我正在尝试通过带练习的书学习 haskell。我无法通过这个,我不知道是什么问题。所以我要声明一个 << 定义。在 'a' 的除数少于适当的除数 'b' 的情况下,它应该是正确的。就像 6 << 10,6 有 4 个除数,10 有 2 个真除数,所以它应该是 False。我已经为除数和适当的除数做了一个定义,但是当我试图使用它们时,它不会发生。
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
已修复
您的 <<
运算符需要类型 Integral a => a -> a -> Bool
,因为 div
和 mod
都需要 Integral
,而不仅仅是 Num
.如果你不能使用 Integral
约束,那么你将不得不编写自己的 div
和 mod
版本,它们适用于所有 Num
s.
如果你注释掉所有的类型签名就可以看到:
> :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
约束。