枚举类型不相等

时间:2017-03-11 14:47:51

标签: haskell equality enumerable

Enum表示可以映射到整数或从整数映射的类型。

可以测试整数是否相等。

是否有一个不想要Eq的Enum实例?

1 个答案:

答案 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)。