Function from `mappend` function to `Monoid` instance?

前端 未结 1 1697
無奈伤痛
無奈伤痛 2021-01-14 08:05

I have a data structure (it\'s a specific subclass of rose-tree that forms a lattice with greatest-lower bound and lowest-upper bound functions), and it supports two perfect

相关标签:
1条回答
  • 2021-01-14 08:42

    You can create "local" instances of Monoid on the fly, using the tools in the reflection package. There's a ready-made example in the repository. This answer explains it a little.

    This is a newtype wrapper over values of type a, on which we will define our Monoid instance.

    newtype M a s = M { runM :: a } deriving (Eq,Ord)
    

    Notice that there is a phantom type s that does not appear in the right hand side. It will carry extra information necessary for the local Monoid instance to work.

    This is a record whose fields represent the two operation of the Monoid class:

    data Monoid_ a = Monoid_ { mappend_ :: a -> a -> a, mempty_ :: a }
    

    The following is the Monoid instance definition for M:

    instance Reifies s (Monoid_ a) => Monoid (M a s) where
        mappend a b        = M $ mappend_ (reflect a) (runM a) (runM b)
        mempty = a where a = M $ mempty_ (reflect a)
    

    It says: "whenever s is a type-level representation of our Monoid dictionary Monoid_, we can reflect it back to obtain the dictionary, and use the fields to implement the Monoid operations for M".

    Notice that the actual value a passed to reflect is not used, it is passed only as a "proxy" of type M a s that tells reflect which type (s) to use to "bring back the record".

    The actual local instance is constructed using the reify function:

    withMonoid :: (a -> a -> a) -> a -> (forall s. Reifies s (Monoid_ a) => M a s) -> a
    withMonoid f z v = reify (Monoid_ f z) (runM . asProxyOf v)
    
    asProxyOf :: f s -> Proxy s -> f s
    asProxyOf a _ = a
    

    The asProxyOf function is a trick to convince the compiler that the phantom type used in the monoid is the same as the one in the Proxy supplied by reify.

    0 讨论(0)
提交回复
热议问题