haskell-servant / haskell-servant/servant
(:<|>) is not Associative
- Dominant language
- Haskell
- Stars
- 2k
- Forks
- 427
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 5
Description
Hello wonderful servant maintainers,
I guess whether this is actually a bug depends on your expected behaviour, but I wasn't easily able to find the expected behaviour written down anywhere (maybe I just missed it);
Given that `:<|>` is defined in `Servant.API.Alternative` I expected it to be associative, so I was quite surprised when I learned it isn't!
Here's a small reproduction which demonstrates this:
```haskell
type FlatAPI =
("a" :> "b" :> Post '[JSON] Int)
:<|> ("a" :> "b" :> Delete '[JSON] String)
:<|> ("c" :> "d" :> Post '[JSON] Int)
:<|> ("c" :> "d" :> Delete '[JSON] String)
type NestedAPI =
("a" :> "b" :> (Post '[JSON] Int :<|> Delete '[JSON] String))
:<|> ("c" :> "d" :> (Post '[JSON] Int :<|> Delete '[JSON] String))
handlePost :: Handler Int
handlePost = pure 1
handleDelete :: Handler String
handleDelete = pure "hello"
server :: Server FlatAPI
server =
handlePost
:<|> handleDelete
:<|> handlePost
:<|> handleDelete
nestedServer :: Server NestedAPI
nestedServer =
(handlePost :<|> handleDelete) -- < these brackets are required.
:<|> handlePost
:<|> handleDelete
```
I had assumed that `FlatAPI` and `NestedAPI` were equivalent, but it turns out that `NestedAPI` requires you to manually group your server implementations to match the bracketing on your API. Remove the brackets causes it to fail to compile.
If this is expected, that's fine, just letting you know that I got tripped up here 😄
Contributor guide
Assessment
This issue has not been assessed yet.