Извините за ужасное название. Я пытаюсь сделать экземпляр Applicative
для Monad
обертывания типа Monoid
.Аппликационная инстанция для (Monad m, Monoid o) => m o?
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)'
Я понимаю, что то, что я написал выше, не имеет смысла. Вот контекст: я пытаюсь использовать абстракцию compos
, как описано в статье A pattern for almost compositional functions. Исходя из этого дерева (используя версию 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)
Я думаю, что они все должны быть в состоянии абстрагируются путем composFoldM
использования compos
для (Monad m, Monoid o) => m o
структуры. Поэтому использовать его с GADT Applicative
версии compos
см. На странице 575/576 из the paper. Я думаю, что мне нужно создать экземпляр этой структуры. Как мне это сделать? Или я полностью опускаю неправильный путь?
Это похоже на то, что мне нужно! Но как я действительно использую его? Я пытался делать такие вещи, как 'composFoldM f = getCompose. составьте (Compose. WrapMonad. Const. f) ', но это не сработает. Есть ли примеры/объяснения того, как объединить функторы? –
Мой бог. Я, наконец, проработал это через испытание и совершенствование. Наверное, так вы учитесь! Правильная вещь - 'compFoldM f = liftM getConst. распаковатьМонад. getCompose. Состав (Compose. WrapMonad. liftM Const. f) '. : D –
@CallumRogers Это точно! Это одна из приятных вещей в Haskell: контролер типов всегда будет направлять вас к правильному решению. –