haskell / haskell/mtl

Why not use rank 2 polymorphism for `callCC`

Open
#127 13 comments 2 reactions 0 assignees View on GitHub
transformers
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.