purescript/purescript-transformers

callCC type signature?

jqyu opened this issue · 2 comments

jqyu commented

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 a

Rather than the more general:

callCC :: forall a. (forall b. (a -> m b) -> m a) -> m a

I 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 bar

Which failed to type check because foo and bar had different types, so the signature of return wasn't happy.

garyb commented

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.

jqyu commented

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 a

That worked without a hitch.
PR here: #74