The “reader” monad

后端 未结 3 1320
感动是毒
感动是毒 2021-02-07 06:20

OK, so the writer monad allows you to write stuff to [usually] some kind of container, and get that container back at the end. In most implementations, the \"container\" can act

3条回答
  •  长发绾君心
    2021-02-07 06:36

    Supply is based on State, which makes it suboptimal for some applications. For example, we might want to make an infinite tree of supplied values (e.g. randoms):

    tree :: (Something r) => Supply r (Tree r)
    tree = Branch <$> supply <*> sequenceA [tree, tree]
    

    But since Supply is based on State, all the labels will be bottom except for the ones one the leftmost path down the tree.

    You need something splittable (like in @PhillipJF's Comonoid). But there is a problem if you try to make this into a Monad:

    newtype Supply r a = Supply { runSupply :: r -> a }
    
    instance (Splittable r) => Monad (Supply r) where
        return = Supply . const
        Supply m >>= f = Supply $ \r ->
            let (r',r'') = split r in
            runSupply (f (m r')) r''
    

    Because the monad laws require f >>= return = f, so that means that r'' = r in the definition of (>>=).. But, the monad laws also require that return x >>= f = f x, so r' = r as well. Thus, for Supply to be a monad, split x = (x,x), and thus you've got the regular old Reader back again.

    A lot of monads that are used in Haskell aren't real monads -- i.e. they only satisfy the laws up to some equivalence relation. E.g. many nondeterminism monads will give results in a different order if you transform according to the laws. But that's okay, that's still monad enough if you're just wondering whether a particular element appears in the list of outputs, rather than where.

    If you allow Supply to be a monad up to some equivalence relation, then you can get nontrivial splits. E.g. value-supply will construct splittable entities which will dole out unique labels from a list in an unspecified order (using unsafe* magic) -- so a supply monad of value supply would be a monad up to permutation of labels. This is all that is needed for many applications. And, in fact, there is a function

    runSupply :: (forall r. Eq r => Supply r a) -> a
    

    which abstracts over this equivalence relation to give a well-defined pure interface, because the only thing it allows you to do to labels is to see if they are equal, and that doesn't change if you permute them. If this runSupply is the only observation you allow on Supply, then Supply on a supply of unique labels is a real monad.

提交回复
热议问题