끔찍한 제목을 위해 죄송합니다. 나는 Monoid
유형을 포장하는 Monad
에 대해 Applicative
의 인스턴스를 만들려고합니다.(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에 설명 된대로 사용하려고합니다. 이 나무 촬영 (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)
나는이 모든 (Monad m, Monoid o) => m o
구조 composFoldM
사용 compos
함으로써 멀리 추상화 될 수 있어야한다고 생각합니다. GADT Applicative
버전을 compos
페이지와 함께 사용하려면 페이지 575/576에서 the paper을 사용하세요. 이 구조의 Applicative
인스턴스를 만들어야한다고 생각합니다. 어떻게하면 좋을까요? 아니면 잘못된 길로 완전히 빠져드는거야?
내가 필요한 것 같습니다. 하지만 어떻게 실제로 사용합니까? 나는'composFoldM f = getCompose '와 같은 일을 시도했다. compos (WrapMonad, Const. f)를 작성하십시오. '하지만이 방법은 효과가 없습니다. 펑터를 결합하는 방법에 대한 예/설명이 있습니까? –
나의 신. 나는 시험과 개선을 통해 그것을 마침내 해결했다. 나는 이것이 당신이 배우는 방법이라고 생각한다! 올바른 것은'composFoldM f = liftM getConst. unwrapMonad. getCompose. compos (WrapMonad. liftM Const. f)를 작성하십시오. : D –
@CallumRogers 그게 맞아! 그것은 하스켈에 관한 좋은 점 중 하나입니다. 유형 검사기는 항상 올바른 해결책을 제시 할 것입니다. –