9

わかりましたので、パッケージを使用して実装する方法を理解しましたReader(および、表示されていません):ReaderToperational

{-# LANGUAGE GADTs, ScopedTypeVariables #-}

import Control.Monad.Operational

data ReaderI r a where
    Ask :: ReaderI r r

type Reader r a = Program (ReaderI r) a

ask :: Reader r r
ask = singleton Ask

runReader :: forall r a. Reader r a -> r -> a
runReader = interpretWithMonad evalI
    where evalI :: forall b. ReaderI r b -> (r -> b)
          evalI Ask = id

しかし、これを無料のモナドで行う方法を一生理解できません (私は Edward Kmett のfreeパッケージを使用しています)。私が得た最も近いものはこれです。これは不正行為であると理解しています((->) r)(すでにモナドである方法についての何か):

import Control.Monad.Free

type Reader r a = Free ((->) r) a

ask :: Reader r r
ask = Free Pure

runReader :: Reader r a -> r -> a
runReader (Pure a) _ = a
runReader (Free k) r = runReader (k r) r

-- Or, more simply and tellingly:
--
-- > runReader = retract

これが私が思っているほど愚かではなかったとしても、基本的に私が欲しいのはReaderデータとして検査できるようにすることなので、それは私が望むものではありません...

4

2 に答える 2

3

彼らがあなたのやり方をしない限り、それはできないと思います。でも、これは読者に限ったことではないと思います。フリーのモナドバージョンの writer を考えてみましょう

data WriterF m a = WriterF m a deriving (Functor)

type Writer m = Free (WriterF m)

は明らかにWriterFwriter と同形ですが、これは単純な代数で期待されるように動作します。

algebraWriter :: Monoid m => WriterF m (m,a) -> (m,a)
algebraWriter (WriterF m1 (m2,a)) = (m1 <> m2,a)

したがって

runWriter :: Monoid m => Writer m a -> (m,a)
runWriter (Pure a) = (mempty,a)
runWriter (Free x) = algebraWriter . fmap runWriter $ x

同様に、私は Free リーダーを次のように考えています。

type ReaderF r = (->) r

type Reader r = Free (ReaderF r)

それらを追加すると状態モナドが得られるので、私はこれが好きです

type State x = Free ((ReaderF x) :+: (WriterF x))

runState :: State x a -> x -> (a,x)
runState (Pure a) x                    = (a,x)
runState (Free (Inl f)) x              = runState (f x) x
runState (Free (Inr (WriterF x f))) _  = runState f x

Free運用ソリューションは、「フリーファンクター」を使用して動作するように作成できることに注意してください。

data FreeFunctor f x = forall a. FreeFunctor (f a) (a -> x)

しかし、それFreeFunctor ReaderIは にも同形(->)です。

于 2013-03-15T08:39:52.583 に答える
1

さて、私はこれを 3 時間見ていて、もっと気に入ったものを見つけたと思います。アプリカティブはモナドReaderと同じなので、次のアプリカティブ バージョンを試すことができます。Readeroperational

{-# LANGUAGE RankNTypes, GADTs, FlexibleInstances #-}

import Control.Applicative

data ProgramA instr a where
    Pure  :: a -> ProgramA r a
    Ap    :: ProgramA r (a -> b) -> ProgramA r a -> ProgramA r b
    Instr :: instr a -> ProgramA instr a

infixl `Ap`

instance Functor (ProgramA instr) where
    fmap f (Pure a) = Pure (f a)
    fmap f (ff `Ap` fa) = ((f .) <$> ff) `Ap` fa
    fmap f instr = Pure f `Ap` instr

instance Applicative (ProgramA instr) where
    pure = Pure
    (<*>) = Ap

interpretA :: Applicative f =>
              (forall a. instr a -> f a)
           -> ProgramA instr a
           -> f a
interpretA evalI (Pure a) = pure a
interpretA evalI (ff `Ap` fa) = interpretA evalI ff <*> interpretA evalI fa
interpretA evalI (Instr i) = evalI i

data ReaderI r a where
    Ask :: ReaderI r r

type Reader r a = ProgramA (ReaderI r) a

ask :: Reader r r
ask = Instr Ask

runReader :: Reader r a -> r -> a
runReader = interpretA (\Ask -> id)

instance Monad (ProgramA (ReaderI r)) where
    return = pure
    ma >>= f = runReader <$> fmap f ma <*> ask

a の構造は、またはProgramA (ReaderI r) a)よりも簡単に調べることができます。Program (ReaderI r) aFree ((->) r) a

于 2013-03-15T11:19:27.230 に答える