(Monad m,Monoid o)的应用实例=>嗯?

时间:2013-08-17 23:15:31

标签: haskell monads gadt applicative monoids

抱歉这个可怕的头衔。我正在尝试为Applicative包装Monad类型的Monoid实例。

instance (Monad m, Monoid o) => Applicative (m o) where
    pure x = return mempty
    xm <*> ym = do
        x <- xm
        y <- ym
        return $ x `mappend` y

这不起作用; GCHi抱怨:

Kind mis-match
The first argument of `Applicative' should have kind `* -> *',
but `m o' has kind `*'
In the instance declaration for `Applicative (m o)'

我意识到我上面写的内容可能毫无意义。以下是上下文:我正在尝试使用文档A pattern for almost compositional functions中描述的compos抽象。拿这棵树(使用GADT版本compos;我已经简化了很多):

data Tree :: * -> * where
    Var :: String -> Expr
    Abs :: [String] -> Expr -> Expr
    App :: Expr -> [Expr] -> Expr

class Compos t where
    compos :: Applicative f => (forall a. t a -> f (t a)) -> t c  -> f (t c)

instance Compos Tree where
    compos f t =
        case t of
            Abs ps e -> pure Abs <*> pure ps <*> f e
            App e es -> pure App <*> f e <*> traverse f es
            _ -> pure t

我将编写许多函数,这些函数会下降树并返回一个说错误列表或一组字符串,同时还需要状态(如绑定环境),例如:

composFoldM :: (Compos t, Monad m, Monoid o) => (forall a. t a -> m o) -> t c -> m o
composFoldM f = ??? 

checkNames :: (Tree a) -> State (Set Name) [Error]
checkNames e =
    case e of
        Var n -> do
            env <- get
            -- check that n is in the current environment
            return $ if Set.member n env then [] else [NameError n]
        Abs ps e' -> do
            env <- get
            -- add the abstractions to the current environment
            put $ insertManySet ps env
            checkNames e'
        _ -> composFoldM checkNames e

data Error = NameError Name
insertManySet xs s = Set.union s (Set.fromList xs)

我认为通过composFoldMcompos结构(Monad m, Monoid o) => m o使用Applicative,可以将这些全部抽象出来。因此,请将其与the paper第575/576页上的composApplicative版本一起使用。我想我需要建立一个这个结构的{{1}}实例。我该怎么做?还是我完全走错了路?

1 个答案:

答案 0 :(得分:5)

您希望Constant包中的Data.Functor.Constant适用transformers,您可以找到here

Applicative具有以下实例:

instance (Monoid a) => Applicative (Constant a) where
    pure _ = Constant mempty
    Constant x <*> Constant y = Constant (x `mappend` y)

然后,您可以使用Constant Compose(也在Data.Functor.Compose包中)使用transformers与任何其他申请人撰写Compose,您可以找到here

Applicativeinstance (Applicative f, Applicative g) => Applicative (Compose f g) where pure x = Compose (pure (pure x)) Compose f <*> Compose x = Compose ((<*>) <$> f <*> x) 个实例:

Compose

然后,您可以ConstantApplicativeState应用与其他任何Monoid(例如{{1}})同时保留某个状态和正在运行的{{1}}计数器。< / p>

更一般地说,您应该阅读论文The Essence of the Iterator Pattern,其中更详细地讨论了这些模式。