Why not use rank 2 polymorphism for `callCC`
- Dominant language
- Haskell
- Stars
- 401
- Forks
- 72
- PR merge metrics
- No merged PRs in 30d
Description
I think rank 2 polymorphism is a must-have for `callCC`, or this code will not compile:
```haskell
f :: Int -> String
f x = (`runCont` id) $ callCC $ \exit -> do
y <- case x of
0 -> exit "error: x == 0"
_ -> pure x
yString <- case y of
1 -> exit "error: y == 1"
_ -> pure $ show y
pure yString
```
When calling functions like `error`, `throwIO`, or `exit`, which will never produce "normal" outputs, I generally expect the return type to be `forall a. a` in order to fit in any hole. But the `exit` produced by `callCC` does not work as expected. I wonder is there any specific reason?
I tried searching for related discussions, but all I could find is [this article](https://wiki.haskell.org/MonadCont_done_right). It seems nobody is bothered by this? I have to use `absurd` to make it work in my code (`absurd <$> exit "error: x == 0"`). I'm curious about how others deal with this lack of polymorphism.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by inspecting the mtl callCC definition and its type signature, then reproduce the supplied f example and compare it with the MonadCont_done_right article. Done should be a maintainer-backed explanation or a clearly scoped decision about whether rank-2 polymorphism is required.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- haskell
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100