haskellenumsbounded-types# How can I determine if one Enum value is the successor of another?

I'm trying to write a function that tells me whether one `Enum`

is the successor of another. Here was my first attempt:

```
isSuccessorOf x y = x == succ y
```

Looks reasonable. Let's try it:

```
λ> isSuccessorOf 3 2
True
λ> isSuccessorOf 1 5
False
λ> isSuccessorOf 3 (maxBound :: Int)
*** Exception: Prelude.Enum.succ{Int}: tried to take `succ' of maxBound
```

Whoops. That should have been `False`

. Let's make sure we don't try to do `succ maxBound`

:

```
isSuccessorOf x y = y /= maxBound && x == succ y
```

Let's try it again:

```
λ> 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)
```

Hmm, now it only works on bounded types. I'd like to avoid needing a separate function for unbounded and bounded `Enum`

s, especially if there's nothing at compile-time to keep you from using the unbounded function on a bounded type. Let's use an `Ord`

constraint instead:

```
isSuccessorOf x y = x > y && x == succ y
```

And let's try it:

```
λ> isSuccessorOf 3 (maxBound :: Int)
False
λ> isSuccessorOf 3 (2 :: Integer)
True
```

But now I'm making an unwarranted assumption. Let's try one more thing (note: this depends on `Down`

having an `Enum`

instance, which it only has in GHC 8.10):

```
λ> import Data.Ord (Down(..))
λ> let delisleFreezing = Down 150
λ> isSuccessorOf (succ delisleFreezing) delisleFreezing
False
```

Well that's less than ideal.

So is there any way to do this seemingly-simple task, without one of these three flaws?

- Fails to compile for types that aren't
`Bounded`

- Bottoms for types that are
`Bounded`

- Gives the wrong answer for types where
`succ x > x`

doesn't hold

Solution

Perhaps a more safe way to check this is making use of ** enumFromTo**, and check if the second item of the list is the successor we are looking for. We can, like you say, simply pattern match on a list with two elements, we do not need to check if that second element is indeed

`y`

:```
isSuccessorOf :: Enum a => a -> a -> Bool
isSuccessorOf y x
| [_,_] <- [x .. y] = True
| otherwise =
```**False**

or we can, like @chi says use this to look if there is a successor:

```
succMaybe :: Enum a => a -> Maybe a
succMaybe x = case
```**[x ..]** of
(_:z:_) -> Just z
_ -> Nothing

- Haskell fails to infer the return type of a monad after using the sequence operator
- Does extracting values from a multiple Value return in Haskell invoke the function more than once?
- How to specify c/c++ compiler on stack install command
- Why do I get "Unexpected reply type" from notify-send when using this Haskell notification server?
- Don't understand notation of morphisms in Monoid definition
- Foldln in haskell
- Is this property of a functor stronger than a monad?
- How to Instantiate a Custom Data Type with Record Syntax and Multiple Constructors
- How do I make a minimal working example for the a DBus server?
- Is it safe to downgrade Haskell stack version?
- Haskell, list of natural number
- unfamiliar syntax in Haskell / Clash function type signature
- foldM with monad State does not type check
- Why does my Runge-Kutta implementation oscillate to 0?
- How do I get the desired behavior in my TCP server?
- Why does the Haskell PVP describe new functions as non-breaking?
- How do I correctly use toLower in Haskell?
- How can I write a notification server in Haskell?
- Every Lens' is a Traversal'... how?
- How do I crate a value of type a{sv} for a call to org.freedesktop.Notifications.Notify via DBus?
- Web Scraping With Haskell
- Double exclamation marks in Haskell
- Haskell Servant POST FormUrlEncoded for (Vector String) field
- Confusion about list types in Haskell
- Idiomatic way to define new vs persisted types in Haskell
- Why does Cabal, unlike GHC, not automatically enable GeneralizedNewtypeDeriving if I explicitly enabled DerivingStrategies?
- What is the proper way of wrapping an Int (not a general type) in another type if type safety is the only motive?
- Parsing inside `between` with Megaparsec
- takeWhile implementation in JavaScript - Looking for better ideas
- How to setup MINGW environment variables for Haskell language server in vscode?