-
Notifications
You must be signed in to change notification settings - Fork 146
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
[WIP] feat(std): add monad transformer interface, StateT, and LazyT #686
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some nits for some more idiomatic code but otherwise looks good 👍 . Some tests, (doc or in tests/pass
) would be nice but maybe that can wait till later as State
could be implemented in terms of StateT
and it would then get tested by the current tests.
Something I have been thinking about is that std
's top level (https://gluon-lang.org/doc/nightly/std/std.html) has become rather crowded so for the next version I will likely try and move some stuff into sub-modules. Maybe it makes sense to put these under std.transformer
or std.monad.transformer
? Without being sure about where to put them it might make more sense to wait with that however.
Thanks. I'll make those changes as soon as I get the chance. Any tests I add might take a bit longer, since that's another area I don't have much experience with.
I think it makes sense to merge |
The previous, naive subsume_implicit function did not traverse the functions simultaneously so the implicit arguments would be lost if the left side had a `forall` at the top. Fixes an issue found in gluon-lang#686 cc @Etherian
The previous, naive subsume_implicit function did not traverse the functions simultaneously so the implicit arguments would be lost if the left side had a `forall` at the top. Fixes an issue found in gluon-lang#686 cc @Etherian
688: fix(check): Subsume implicit functions with forall correctly r=Marwes a=Marwes The previous, naive subsume_implicit function did not traverse the functions simultaneously so the implicit arguments would be lost if the left side had a `forall` at the top. Fixes an issue found in #686 cc @Etherian Co-authored-by: Markus Westerlind <[email protected]>
…g function arguments Otherwise spurious errors about illegal self recursion would be triggered as it looks like we are reducing the same alias twice. Found in gluon-lang#686 cc @Etherian
689: fix(check): The alias reduction stack must be cleared between unifyin… r=Marwes a=Marwes …g function arguments Otherwise spurious errors about illegal self recursion would be triggered as it looks like we are reducing the same alias twice. Found in #686 cc @Etherian Co-authored-by: Markus Westerlind <[email protected]>
It think there is still value in having monad transformers as they have their uses. If they end up being replaced by effects in 99% of cases monad transformers could still be factored out of the standard library and into an external library for those who need it. |
I was writing tests for StateT when I ran into some issues. (Ignore the error mentioned on line 26. Looking back at my logs, that appears to have been due to a typo.)
The type checker sometimes seems to have trouble finding buried
I'm not sure what I'm doing wrong here.
There's not actually an issue here. I left the unfinished code in lines 41-44 to point out an anomaly in the error messages: they refer to the |
It appears that records are only traversed once to pull out the implicit instances so it finds Going to have to sleep on this one.
Here you have forgotten to export the
Implicit resolution seems to do something weird here, haven't looked into it further. |
Traverses records fully to bring their implicit instances in scope (`Monad -> Applicative -> Functor` etc) Found in gluon-lang#686 cc @Etherian
Traverses records fully to bring their implicit instances in scope (`Monad -> Applicative -> Functor` etc) Found in gluon-lang#686 cc @Etherian
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Looks good to me. Either remove or fix the TODO and I would be happy to merge!
assert_eq (eval_state_t ((mx >>= f) >>= g) s) (eval_state_t (mx >>= (\x -> f x >>= g)) s) | ||
|
||
group "statet" [ | ||
// should this be moved to std.monad? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That might be useful but we don't have to do that here and now.
I decided to not include the unfinished tests, so the PR should be ready to merge. I do have a question, though, about one of the issues I had while trying to write them. Why does the implicit parameter of
|
Implicits are resolved just before generalisation just as in https://arxiv.org/pdf/1512.01895.pdf . The short of it is that since type inference and implicit resolution depend on each other when we chose to do implicit resolution affects type inference and therefore whether the program is well typed. Since we also want typing to be predictable, choosing to do implicit resolution just before generalization on the closest let binding is the easiest to follow solution. Most of the time it is not an issue since the type will be concrete (say As an aside, we could chose to infer that signature instead of demanding a concrete type. However I would argue that it is usually not what you want. Introducing an implicit argument makes the binding a function so using it elsewhere involves a function call, making it more costly than one might expect. While this is basically https://wiki.haskell.org/Monomorphism_restriction which has a fair share of critque, gluon has scoped type variables by default so I think it avoids most of actual problems. Looks like tests are failing after the rebase since you now need to import |
Thanks for the explanation! Do you think it would be viable to suggest the inferred signature in the error message? That way we could keep the difference in signature explicit while also smoothing the learning curve for newbies like myself.
Ah, that explains it. I won't have access to my computer over the weekend, but if you made the tweaks I could accept them over the phone. Or I could just do it Monday. |
Good idea! Created an issue #725 |
Import Lazy explicitly in std.lazyt
bors r+ |
686: [WIP] feat(std): add monad transformer interface, StateT, and LazyT r=Marwes a=Etherian ## Description Adds a monad-transformer interface `Transformer`, a State monad transformer `StateT`, and a Lazy monad transformer `LazyT` to the standard library. ## Related PRs Lays groundwork for Streamlike and the new parser #687. ## Status **In Development** ### Outstanding design questions - [x] ~~Can and should `StateT` be replaced by the effects system?~~ ([not for the time being, at least](#686 (comment))) - [ ] Should `Transformer` require `monad` field? - [ ] Should StateT and LazyT (and other monad transformers) be merged with their non-transformer counterparts? ### To Do - [x] ~~Fix StateT's implicit parameter bugs~~ (#688 & #689) - [ ] add tests - [ ] add inline docs ## Prior Art - StateT - [Haskell](https://hackage.haskell.org/package/transformers-0.5.6.2/docs/src/Control.Monad.Trans.State.Lazy.html#StateT) - [Idris](https://github.com/idris-lang/Idris-dev/blob/master/libs/base/Control/Monad/State.idr) - [Implementing Applicative (<*>) for StateT](https://stackoverflow.com/questions/27903650/implementing-applicative-for-statet) - MonadTrans - [Haskell](https://hackage.haskell.org/package/transformers/docs/src/Control.Monad.Trans.Class.html#MonadTrans) - [Idris](https://github.com/idris-lang/Idris-dev/blob/master/libs/base/Control/Monad/Trans.idr) Co-authored-by: Etherian <[email protected]> Co-authored-by: Markus Westerlind <[email protected]>
Build succeeded |
Description
Adds a monad-transformer interface
Transformer
, a State monad transformerStateT
, and a Lazy monad transformerLazyT
to the standard library.Related PRs
Lays groundwork for Streamlike and the new parser #687.
Status
Merged
Outstanding design questions
Can and should(not for the time being, at least)StateT
be replaced by the effects system?Should(Basing monads on their transformers is the better option)Transformer
requiremonad
field?To Do
Fix StateT's implicit parameter bugs(fix(check): Subsume implicit functions with forall correctly #688 & fix(check): The alias reduction stack must be cleared between unifyin… #689)add testsPrior Art