Enum表示可以映射到整数或从整数映射的类型。
可以测试整数是否相等。
是否有一个不想要Eq的Enum实例?
答案 0 :(得分:3)
只有Enum
不足以提供相等测试,因为Int
是有界的。假设我们有以下功能,您可能会想到这一点。
eqEnum :: Enum a => a -> a -> Bool
eqEnum x y = fromEnum x == fromEnum y
现在我们可以生成两个不一致的Integer
:
ghci> eqEnum 0 (2 + 2 * toEnum (maxBound :: Int))
True
我们还可以查看Double
:
ghci> eqEnum 3.0 pi
True
嗯,哎呀。 Enum
不会产生正确的Eq
实例。我们甚至可以进一步为Enum
实例创建一个Eq
实例的实例:
newtype Foo = Foo { unFoo :: Integer -> Integer }
instance Enum Foo where
fromEnum (Foo f) = fromEnum $ f 0
toEnum n = Foo (+ toInteger n)
succ = Foo . succ . unFoo -- not necessary
pred = Foo . pred . unFoo -- not necessary
我们可以使用该伪实例来枚举函数族F_n(x) = x + n
:
> map ((\f -> unFoo f 0) . toEnum) [0..100]
[0,1,2,...,100]
但是,无法确定两个Foo
函数是否相同。而且,与Double
一样,Foo
实际上无法恢复的toEnum . fromEnum
个值很多:
ghci> toEnum . fromEnum $ pi :: Double
3.0
ghci> let f = toEnum . fromEnum $ Foo (const 0) :: Foo
ghci> unFoo f 0
0
ghci> unFoo f 1 -- not constant anymore
1
基本问题是Enum
没有法律规定。您需要转换为Int
。但最后,这并不奇怪,因为它们是originally meant for [x..y]
(又名enumFromTo x y
)。