5

ひどいタイトルでごめんなさい。である型をラップするApplicativeためのインスタンスを作成しようとしています。MonadMonoid

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 most compositional functions でcompos説明されているように、抽象化を使用しようとしています。このツリーを取得します ( の 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そのため、論文の 575/576 ページにある の GADTApplicativeバージョンで使用します。この構造のインスタンスを作成する必要があると思います。どうすればいいですか?それとも、完全に間違った道を進んでいますか?composApplicative

4

1 に答える 1

5

ここで見つけることができるパッケージからのConstantアプリケーションData.Functor.Constantが必要です。transformers

これApplicativeには次のインスタンスがあります。

instance (Monoid a) => Applicative (Constant a) where
    pure _ = Constant mempty
    Constant x <*> Constant y = Constant (x `mappend` y)

次に、from (パッケージにも含まれています)Constantを使用して、他のアプリケーションで構成できます。これは、こちらにあります。ComposeData.Functor.Composetransformers

ComposeこのApplicativeインスタンスがあります:

instance (Applicative f, Applicative g) => Applicative (Compose f g) where
    pure x = Compose (pure (pure x))
    Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)

次にComposeConstantアプリケーションを他のApplicativeもの ( など) と一緒に使用して、状態と実行中の集計Stateの両方を維持できます。Monoid

より一般的には、これらのパターンについて詳しく説明している論文The Essence of the Iterator Patternを読む必要があります。

于 2013-08-18T01:10:22.200 に答える