-
Notifications
You must be signed in to change notification settings - Fork 65
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
Missing laws #5
Comments
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.90.2560 provides an identical set of laws to the ones I'd expect. |
I'm currently mulling over my MonadState
MonadReader
In particular, the last example shows how to lift a control operation in a unique way, something which I didn't think was possible. These laws are not an a-priori characterization, they only hold for monad transformers. You need to walk down the transformer stack to see how they relate to each other. For instance, to see that
one has to unpeel all the intermediate (Actually, I think that a-priori laws are not a complete story, you also need to know how the instances are lifted through a monad transformer.) |
I can at least see stating those as laws that |
The class for the writer monad is weird because it has so many control operations. I think the laws for a monad transformer should be: MonadWriter
The laws for |
@ekmett That paper states modify f >> modify g = modify (g . f) -- modify-modify
get >>= \s1 -> get -> \s2 -> return (s1, s2) = get >>= \s -> return (s, s) -- get-get
get >>= \s1 -> modify f >> get >>= \s2 -> return (s1, s2) = get >>= \s -> modify f >> return (s, f s) -- get-modify-get Since mtl's get >>= \s1 -> get -> \s2 -> return (s1, s2) = get >>= \s -> return (s, s) -- get-get (the same)
get >>= \_ -> put s = put s -- get-put
put s1 >> put s2 = put s2 -- put-put
put s >> get = put s >> return s -- put-get The following get >>= \s -> put s = return () -- get-put-2 In a similar vein, one might think of void get = return () -- get-void Are the equations above general enough? Is there a litmus test for sufficiently general This may just be my wishful thinking, but one nice-sounding property is that any sequence of EDIT: I have a lot to read; I could find these laws mentioned in various places. http://gallium.inria.fr/blog/lawvere-theories-and-monads/ |
For (,) <$> ask <*> ask = (\r -> (r, r)) <$> ask -- ask-ask
local f ask = fmap f ask -- local-ask
local f . local g = local (g . f) -- local-local
local f (return x) = return x -- local-M-return
local f (m >>= \x -> k x) = local f m >>= \x -> local f (k x) -- local-M-bind |
Could your ask >> ask = ask ? |
@ocharles Right, that looks equivalent and simpler. Formally speaking, I'm missing a step to prove that |
You could probably go even stronger with something like m <*> ask = ask <**> m
ask *> m = m = m <* ask to show that |
Also: at the very least, |
Interesting, these homomorphisms imply a lot of the laws. For example, obviously in |
This commit closes scalaz#1658
Any progress on finalizing these laws and adding them to the documentation? |
Thanks for the reminder @recursion-ninja . I think this issue was a victim of "perfect is the enemy of good". There are so many ways to present the laws, and comparing them all against each other is a deep rabbit hole. I just opened PR #61 to get things started. |
The -- Laws for get and put
get = state $ \s -> (s, s)
put s = state $ const $ ((), s)
-- Law for state joining
state f >>= state . g = state $ uncurry g . f Also, I'm wondering whether -- These laws specify the basic behavior of the passed continuation.
-- callCC itself has no side effects.
callCC (const m) = m
-- The continuation passed returns the given value.
callCC ($ a) = pure a
-- It also does so in the presence of side effects.
callCC ((>>=) m) = m
-- The return value of the continuation passed is actually Void, so it doesn't "really" return.
callCC f = callCC (f . fmap absurd)
-- And then this law I think would allow decomposition of the behavior of callCC by induction into the base cases. Though I'm not sure if it actually works that way.
callCC (\k -> f k >>= (\a -> k a >>= g k)) = callCC f I'm also not sure whether the situation with |
@Zemyla Those laws look great! Here they are QuickChecked: https://github.com/Lysxia/checkers-mtl/blob/d30c35ea87d1746bbd2d1728abd0045f8355b650/src/Test/Monad/Cont.hs The tests pass with those monads at least: https://github.com/Lysxia/checkers-mtl/blob/d30c35ea87d1746bbd2d1728abd0045f8355b650/src/Test/Monad/Cont/Checkers.hs#L36-L39 |
Keep forgetting to note here, that as soon as the laws are decided on and a PR is merged, i will add them to quickcheck-classes and hedgehog-classes. |
It'd be great to actually get this sorted. The control operations are a horrible mess for things like |
I've pretty well convinced myself that this obeys the `MonadReader` laws [proposed by Heinrich Apfelmus](haskell/mtl#5 (comment)) and the ones [proposed by Li-yao Xia](haskell/mtl#5 (comment)), so I think it should be added.
I've pretty well convinced myself that this obeys the `MonadReader` laws [proposed by Heinrich Apfelmus](haskell/mtl#5 (comment)) and the ones [proposed by Li-yao Xia](haskell/mtl#5 (comment)), so I think it should be added.
* I've pretty well convinced myself that this instance obeys the `MonadReader` laws [proposed by Heinrich Apfelmus](haskell/mtl#5 (comment)) and the ones [proposed by Li-yao Xia](haskell/mtl#5 (comment)), so I think it should be added. * The `MonadState` instance is trivial.
* I've pretty well convinced myself that this instance obeys the `MonadReader` laws [proposed by Heinrich Apfelmus](haskell/mtl#5 (comment)) and the ones [proposed by Li-yao Xia](haskell/mtl#5 (comment)), so I think it should be added. * The `MonadState` instance is trivial.
* I've pretty well convinced myself that this instance obeys the `MonadReader` laws [proposed by Heinrich Apfelmus](haskell/mtl#5 (comment)) and the ones [proposed by Li-yao Xia](haskell/mtl#5 (comment)), so I think it should be added. * The `MonadState` instance is trivial.
* I've pretty well convinced myself that this instance obeys the `MonadReader` laws [proposed by Heinrich Apfelmus](haskell/mtl#5 (comment)) and the ones [proposed by Li-yao Xia](haskell/mtl#5 (comment)), so I think it should be added. * The `MonadState` instance is trivial. Closes nikita-volkov#23.
* I've pretty well convinced myself that this instance obeys the `MonadReader` laws [proposed by Heinrich Apfelmus](haskell/mtl#5 (comment)) and the ones [proposed by Li-yao Xia](haskell/mtl#5 (comment)), so I think it should be added. * The `MonadState` instance is trivial. Closes nikita-volkov#23.
* I've pretty well convinced myself that this instance obeys the `MonadReader` laws [proposed by Heinrich Apfelmus](haskell/mtl#5 (comment)) and the ones [proposed by Li-yao Xia](haskell/mtl#5 (comment)), so I think it should be added. * The `MonadState` instance is trivial. Closes nikita-volkov#23.
@HeinrichApfelmus, I'd expect a law relating listen (tell w) = ((), w) <$ tell w |
The laws for
MonadState
, etc. are missing from the haddocks.It may be a good idea to add them.
The text was updated successfully, but these errors were encountered: