【发布时间】:2013-08-17 23:15:31
【问题描述】:
对不起,糟糕的标题。我正在尝试为 Monad 创建一个 Applicative 的实例,以包装 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 抽象。采用这棵树(使用compos 的 GADT 版本;我已经简化了很多):
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)
我认为这些都应该可以通过使composFoldM 使用compos 来抽象出(Monad m, Monoid o) => m o 结构。因此,要将其与compos 的 GADT Applicative 版本一起使用,请参见 the paper 的第 575/576 页。我想我需要为这个结构创建一个Applicative 实例。我该怎么做?还是我完全走错了路?
【问题讨论】:
标签: haskell monads gadt applicative monoids