Closed Atry closed 4 years ago
There are a few issues with this.
There are some reasons we might want overlap that have been detailed on the GHC Trac 1, but they can have weird interactions and generally go against the design philosophy of mtl-style coupling (in this case, r
and m
). Overall it would cause breakage, confusion, and be at least mildly betraying to mtl. The benefit is not worth it at all in my estimation. If you want multiple effects ala State, Except, etc., a different effect system may be desirable to you. I urge you to read the conversation in 1 as it contains a wealth of useful information related to this topic.
In the case of ReaderT, ReaderT r (ReaderT r' m)
is the same as ReaderT (r, r') m
.
Closing for now, if you have any questions or concerns or want to make a case that this should be merged, feel free to re-open. Though, to be clear, I think the chances of that happening are near zero. At the very least, this could spark useful discussion toward other improvements.
Thanks!
I am aware that a) ticket is already closed b) I'm asking for free knowledge here so I'm ok if this goes unanswered but @chessai if you would be so kind, could you elaborate a bit more why:
"it would cause breakage, confusion" Why ppl would be confused? What would break?
"be at least mildly betraying to mtl." Why that would betray MTL?
As far as I see it, the limitations of Functional Dependencies were the first things that made me explore other alternatives (polysemy). At that time I did not even know (to be honest) that it was due too the FunDep, I just could not simply do in MTL multiple error types, multiple states.
1.)
Every attempt to asks
with a function that is at all polymorphic in the argument type breaks in the scenario painted here, so almost every single invocation of ask
everywhere would have to use explicit type applications. If you want to work with anything polymorphic where you have instances to pick things out? Scoped type variables everywhere so you can even name the types involved. There is a ton of code out there written in a (HasFoo e, HasBar e, HasQuux s, MonadReader e m, MonadState s m) => m a
or which works in Haskell 98 + fundeps. None of that survives.
It is picking out a different point in the design space, but not one that is better.
2.) I wasn't the one who chimed in with the 'betrayal' bit, but the mtl
is a pretty stable beast. It has been around for a long time, and there is a huge edifice of code built on top of it. Changing it willy-nilly to move to a state that isn't actually observably better shouldn't be done lightly. I would strongly reject a proposal to make this sort of change to the library. There are other libraries that build on top of transformers
and strip out the fundeps, or which replace the fundeps with type families. The fun thing is you don't even have to give up access to the mtl
for everything else, because the types are shared. This was the motivation behind splitting the mtl and transformers in the first place.
Currently
ReaderT
does not pass through nestedMonadReader
instances. If this PR get merged, multipleMonadReader
s can be supported. For example, given the following type:It should supports both the following type classes:
MonadReader String X
MonadReader Double X
We can then read either
String
orDouble
withTypeApplications
language extension: