我正在尝试编写一个函数来告诉我是否Enum
是另一个人的继承者。这是我的第一次尝试:
isSuccessorOf x y = x == succ y
看起来很合理。我们来尝试一下:
λ> isSuccessorOf 3 2
True
λ> isSuccessorOf 1 5
False
λ> isSuccessorOf 3 (maxBound :: Int)
*** Exception: Prelude.Enum.succ{Int}: tried to take `succ' of maxBound
哎呀。那应该是False
。让我们确保我们不会尝试做succ maxBound
:
isSuccessorOf x y = y /= maxBound && x == succ y
让我们再试一次:
λ> isSuccessorOf 3 (maxBound :: Int)
False
λ> isSuccessorOf 3 (2 :: Integer)
<interactive>:2:1: error:
• No instance for (Bounded Integer)
arising from a use of ‘isSuccessorOf’
• In the expression: isSuccessorOf 3 (2 :: Integer)
In an equation for ‘it’: it = isSuccessorOf 3 (2 :: Integer)
嗯,现在它只适用于有界类型。我想避免需要单独的无界和有界函数Enum
s,特别是如果编译时没有任何东西可以阻止您在有界类型上使用无界函数。让我们使用一个Ord
约束代替:
isSuccessorOf x y = x > y && x == succ y
让我们尝试一下:
λ> isSuccessorOf 3 (maxBound :: Int)
False
λ> isSuccessorOf 3 (2 :: Integer)
True
但现在我做出了一个毫无根据的假设。让我们再尝试一件事(注意:这取决于Down
有一个Enum
实例,仅在 GHC 8.10 中具有):
λ> import Data.Ord (Down(..))
λ> let delisleFreezing = Down 150
λ> isSuccessorOf (succ delisleFreezing) delisleFreezing
False
嗯,这不太理想。
那么有没有什么方法可以完成这个看似简单的任务,而又不存在这三个缺陷之一呢?
- 无法编译不存在的类型
Bounded
- 类型的底部是
Bounded
- 对于其中的类型给出错误的答案
succ x > x
不成立