Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Missing laws #5

Open
ekmett opened this Issue · 4 comments

2 participants

@ekmett
Owner

The laws for MonadState, etc. are missing from the haddocks.

It may be a good idea to add them.

@ekmett ekmett was assigned
@ekmett
Owner

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.

@HeinrichApfelmus

I'm currently mulling over my operational package again, and it appears to me that the following laws should hold for monad transformers:

MonadState

get = lift get
put = lift . put

MonadReader

ask = lift ask
local r (lift   m) = lift (local r m)
local r (return a) = return a
local r (m >>=  k) = local r m >>= local r . k

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

local r ask = fmap r ask

one has to unpeel all the intermediate lift until you end up at the base Reader monad.

(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.)

@ekmett
Owner

I can at least see stating those as laws that MonadReader, MonadState, etc. instances that lift over a transformer can satisfy. Otherwise, obviously, the equations above don't hold in general.

@HeinrichApfelmus

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

tell = lift . tell

listen (lift   m) = lift (listen m)
listen (return a) = return (a,mempty)
listen (m >>=  k) = listen m `combine` listen . k
    where
    combine m k = do
        (a, w1) <- m
        (b, w2) <- k a
        return (b, w1 `mappend` w2)

pass (lift   m)     = lift (pass m)
pass (return (a,f)) = return (a, f mempty)
pass (m >>=  k)     = m `combine` k
    where
    combine m k = do
        (a, w1) <- listen m
        pass (tell w1 >> k a)

The laws for listen resemble a monad morphism, whereas pass is just wacky. Weirdly enough, both seem to reproduce the definition of the writer monad in the first place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.