callCC type signature?
jqyu opened this issue · 2 comments
Pardon my ignorance if I'm misunderstanding what a Cont transformer is, but is there a reason why the callCC type signature is
callCC :: forall a b. ((a -> m b) -> m a) -> m aRather than the more general:
callCC :: forall a. (forall b. (a -> m b) -> m a) -> m aI recently tried to write some code that looked like:
value = callCC \return -> do
foo <- foo' `fallBackTo` return defaultValue
bar <- bar' `fallBackTo` return defaultValue
fn foo barWhich failed to type check because foo and bar had different types, so the signature of return wasn't happy.
I think it's probably fine to move the forall up like that, since the use of b here is only in the return type anyway (because we don't care about the result value).
It's probably the way it is now because it's the same in Haskell, and a lot of stuff was borrowed or straight lifted from there at first. I assume it's this way in Haskell to avoid the need of -XRank2Types/-XRankNTypes.
Hmm, tried actually implementing it and it's much easier said than done. Although the instance declarations for the other monad transformers like ExceptT, MaybeT, StateT, and WriterT should work as-is, they fail to typecheck.
The liftCallCC functions are pretty hard to translate using rank 2 types. Going to have to put some more thought into this before submitting a PR
Whoops, looks like I had the signature wrong! I should've suggested:
callCC :: forall a. ((forall b. a -> m b) -> m a) -> m aThat worked without a hitch.
PR here: #74