Я пытаюсь написать функцию, которая сообщает мне, является ли один 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
, что является новым для GH C 8.10.1):
λ> import Data.Ord (Down(..))
λ> let delisleFreezing = Down 150
λ> isSuccessorOf (succ delisleFreezing) delisleFreezing
False
Что ж, это далеко не идеально.
Итак, есть ли способ выполнить эту, казалось бы, простую задачу без одного из этих трех fl aws?
- Не удается скомпилировать для типов, отличных от
Bounded
- Низ для типов
Bounded
- Дает неправильный ответ для типов, где
succ x > x
не соответствует