适用实例(Monad m,Monoid o)=> mo?

Cal*_*ers 5 monads haskell applicative monoids gadt

抱歉可怕的头衔.我正在尝试创建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
Run Code Online (Sandbox Code Playgroud)

这不起作用; 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)'
Run Code Online (Sandbox Code Playgroud)

我意识到我上面写的内容可能毫无意义.这是上下文:我正在尝试使用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
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

我想这些应该都能够通过使被抽象出来composFoldM使用compos(Monad m, Monoid o) => m o结构.因此,请使用本文第575/576页上的GADT Applicative版本.我想我需要创建一个这种结构的实例.我该怎么做?还是我完全走错了路?composApplicative

Gab*_*lez 5

您希望Constant从应用性Data.Functor.Constanttransformers包,你可以找到这里.

Applicative有以下实例:

instance (Monoid a) => Applicative (Constant a) where
    pure _ = Constant mempty
    Constant x <*> Constant y = Constant (x `mappend` y)
Run Code Online (Sandbox Code Playgroud)

然后Constant,您可以使用Composefrom Data.Functor.Compose(也在transformers包中)使用任何其他应用程序,您可以在此处找到它们.

Compose有这个Applicative实例:

instance (Applicative f, Applicative g) => Applicative (Compose f g) where
    pure x = Compose (pure (pure x))
    Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)
Run Code Online (Sandbox Code Playgroud)

然后你可以和其他任何人一起使用Compose你的Constant应用程序Applicative(比如State)保持一些状态和运行Monoid记录.

更一般地说,您应该阅读论文"迭代器模式的本质",它将更详细地讨论这些模式.