Open int-index opened 8 years ago
Thanks for this post. At this point, with this fork merged, it's best to make a post like this straight to GHC's Trac, for higher visibility. (I'm actually on holiday at the moment and haven't read the details, but will in due course. In the meantime, I'm sure others will chime in.)
Thanks!
The Dependent Haskell Proposal mentions a dependent visible irrelevant quantifier:
forall (...) ->
. Now that we've got visible type application, thanks to Richard's tremendous efforts, I think we're pretty close to getting this quantifier (but surely I might be mistaken).What worries me is the following line in the proposal:
The way I see it,
forall (...) ->
is not useless. It's actually essential if we want to get rid ofProxy
(which I hope everyone agrees is a bit of a hack). Let me describe my use case to make it clear what I mean.Ether is a library that defines tagged monad transformers and classes. Tags allow you to have multiple occurences of the same effect in your monad transformer stack, like multiple
MonadState
s or multipleMonadReader
s. I don't want to steal your time so I won't go much in-depth. It should be enough to mention that tags are simply data types (possibly uninhabited) and they're passed via proxies. So instead of writingask
to get yourMonadReader
environment you writeEther.ask (Proxy :: Proxy MyTag)
whereMyTag
is a tag indicating which environment you want (remember that now you can have more than one).This all actually works quite nicely but proxies are ugly. I thought that I could get rid of them as soon as we get visible type application so the user can write
Ether.ask @MyTag
. Turns out it's not that simple.Consider the type of
Ether.ask :: forall tag r m . MonadReader tag r m => Proxy tag -> m r
. To find an instance forMonadReader tag r m
, we need the to know what thetag
is. We useProxy
to specify it.A naïve attempt to get rid of
Proxy
is to simply remove the argument, since thetag
can now be specified using visible type application. The type becomesEther.ask :: forall tag r m . MonadReader tag r m => m r
. Unfortunately, this fails with an error:Increasing iterations limit makes no difference. I think I can understand why that happens. There's nothing in the type signature to specify what
tag
is, so the dictionary forMonadReader
can't be found. We need to promise to the compiler thattag
will be specified at call site. I believe this is whereforall (...) ->
comes into play. The type ofEther.ask
should beforall tag -> forall r m . MonadReader tag r m => m r
. This type signature is morally equivalent to the one withProxy
, so I'd expect that to work.Thoughts?