2013-03-15 40 views
7

好了,我已經找到了如何使用operational包來實現Reader(和ReaderT,未顯示):如何使用免費monads實現Reader?

{-# 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作爲數據...

+1

我不認爲這可以在沒有函數類型的地方完成。 – 2013-03-15 08:23:34

回答

3

我不認爲它可以做,除非他們的方式。但是,我不認爲這對讀者來說是獨一無二的。考慮作家

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

type Writer m = Free (WriterF m) 

明顯的自由單子版本,WriterF是同構的作家,但是這並不表現我們希望用簡單的代數

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 

方式同樣,我認爲免費閱讀器爲

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也是同構(->)

1

嗯,我一直在看這個3個小時了,我想我找到了一些我更喜歡的東西。由於Reader應用性是一樣的Reader單子,我們可以嘗試的operational一個適用版本:

{-# 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 

一個ProgramA (ReaderI r) a)的結構可以比任Program (ReaderI r) aFree ((->) r) a更直截了當進行檢查。