對不起,可怕的標題。我正在嘗試爲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的好處之一:類型檢查器將始終引導您朝向正確的解決方案。 –