Przepraszamy za okropny tytuł. Próbuję wykonać instancję Applicative
dla zawijania Monad
typu, który jest Monoid
.Applicative Instance dla (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
To nie działa; GCHi narzeka na:
Kind mis-match
The first argument of `Applicative' should have kind `* -> *',
but `m o' has kind `*'
In the instance declaration for `Applicative (m o)'
Zdaję sobie sprawę, że to, co napisałem powyżej, może nie mieć sensu. Oto kontekst: próbuję użyć abstrakcji compos
, jak opisano w artykule A pattern for almost compositional functions. Biorąc to drzewa (przy użyciu wersji GADT z compos
; uprościłem to dużo):
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
zamierzam napisać wiele funkcji, które schodzą z drzewa i zwróci listę mówią błędów lub zestaw strun podczas gdy również wymagający stan jak to idzie w dół (takich jak środowisko wiązanie), takich jak:
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)
myślę, że to powinny być w stanie być wydobywane z dala poprzez composFoldM
korzystanie compos
dla struktury (Monad m, Monoid o) => m o
. Aby więc użyć go z wersją GADT Applicative
z compos
znalezioną na stronie 575/576 z the paper. Myślę, że muszę utworzyć instancję Applicative
tej struktury. Jak to zrobić? Czy też idę całkowicie niewłaściwą ścieżką?
To wygląda na to, czego potrzebuję! Ale w jaki sposób mogę go używać? Próbowałem robić rzeczy takie jak 'composFoldM f = getCompose. compos (Compose, WrapMonad, Const. f) 'ale to nie działa. Czy są jakieś przykłady/objaśnienia, jak łączyć funktory? –
Mój Boże. W końcu udało mi się to osiągnąć dzięki próbom i ulepszeniom. Chyba tak się uczysz! Właściwą rzeczą jest 'composFoldM f = liftM getConst. odwijaj Monoad. getCompose. compos (kompilacja: WrapMonad. liftM Const. f) '. : D –
@CallumRogers Dokładnie tak! To jedna z miłych rzeczy na temat Haskella: kontroler zawsze poprowadzi cię do właściwego rozwiązania. –