对不起,可怕的标题。我正在尝试为Monad
包装一个类型为Monoid
的Applicative
实例。适用实例
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
结构中抽象出来。因此,请使用the paper的第575/576页上的compos
的GADT Applicative
版本。我想我需要制作一个Applicative
这个结构的实例。我将如何做到这一点?或者我完全走错了路?
这看起来像我需要的东西!但我如何真正使用它?我试图做一些事情,比如'composFoldM f = getCompose。 compos(Compose。WrapMonad。Const。f)'但这不起作用。有没有关于如何组合仿函数的例子/解释? –
我的天啊。我终于通过试验和改进完成了。我想这是你如何学习!正确的是'composFoldM f = liftM getConst。 unwrapMonad。 getCompose。 compos(Compose。WrapMonad。liftM Const。f)'。 :D –
@CallumRogers完全正确!这是Haskell的好处之一:类型检查器将始终引导您朝向正确的解决方案。 –