-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Get rid of fmapCoerce by ensuring our functors are representational #64
base: functor-stt-stm
Are you sure you want to change the base?
Conversation
Nice but restrictive. Many |
@phadej Even when fully concrete? I.e. wouldn't When not concrete we can just require |
Indeed the universal instance here when specialized to |
Yes, this works foo :: (forall a b. Coercible a b => Coercible (f a) (f b), Applicative f) => f ()
foo = pure ()
bar :: IO ()
bar = foo
baz :: ReaderT r IO ()
baz = foo
{- Nope
qux :: (Applicative m) => ReaderT r m ()
qux = foo
-}
quux :: (Applicative m, forall a b. Coercible a b => Coercible (m a) (m b)) => ReaderT r m ()
quux = foo |
It works because |
Hmm I see. I don't fully understand why yet, but yes that's not working here to redefine ReaderT as a data type. Are there any real-world examples of such transformers? I'm used to always seeing them as newtypes, and all the ones I could find starting from the instance list of |
It's odd to me that newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
data ReaderTData r m a = ReaderTData { runReaderTData :: r -> m a }
data ReaderTIO r a = ReaderTIO { runReaderTIO :: r -> IO a }
representationalProxy :: (forall a b. Coercible a b => Coercible (f a) (f b)) => Proxy f
representationalProxy = Proxy
p1 :: Proxy (ReaderT r IO)
p1 = representationalProxy
p2 :: Proxy (ReaderTIO r)
p2 = representationalProxy
p3 :: Proxy (ReaderTData r IO)
p3 = representationalProxy |
That because Load into ghci and look for the roles in |
Right, but fully unsaturated |
For more information read through https://www.microsoft.com/en-us/research/uploads/prod/2018/05/coercible-JFP.pdf, in particular section 2.8 Supporting higher order polymorphism and 8.1 Roles for higher-order types TL;DR this needs support from GHC, higher order stuff just doesn't work. |
And to be clear about expectations: I won't merge this, nor work on other issues. GHC doesn't allow me to express what I want, and that was already identified in the original paper introducing roles. |
And FYI:
They should, but they aren't. There are fake functors too, e.g. https://hackage.haskell.org/package/bifunctors-5.5.14/docs/src/Data.Biapplicative.html#Mag and people will complain loudly if you suggest forcing EDIT: I tried to argue against, e.g. One :: a -> Mag a b b has unboxed (equality) coercion, but One :: Coercible b c => a -> Mag a b c would have unboxed one. So I guess you'd need to figure out how to tell GHC to have boxed coercions. So TL;DR, this issue has long history, and sorry that you had to re-learn it. But I'm somewhat frustrated going though arguments every other year. |
Sorry to bring this back up. I've opened https://gitlab.haskell.org/ghc/ghc/-/issues/22644, which I think would help with specifically the issue here without requiring the full solution of higher order roles or the |
Note that I didn't try to minimize the use of
RepresentationalMonad
, since all real functors should be "representational" in this sense anyway, but perhaps some of these changes could be reverted back toMonad
.