好的,所以我已经找到了如何使用operational
包实现Reader
(以及ReaderT
,未显示):
{-# 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
但我无法弄清楚如何使用免费monad(我正在使用Edward Kmett的free
包)来解决这个问题。我得到的最接近的是这个,我理解是作弊(关于((->) r)
如何已经是monad的事情):
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
作为数据......
答案 0 :(得分:3)
我不认为可以做到,除非他们有你的方式。但是,我不认为这对读者来说是独一无二的。考虑免费的monad版本的作家
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)
我喜欢这个,因为添加它们可以获得状态monad
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 :(得分:1)
好吧,我现在已经看了3个小时了,我想我发现了一些我更喜欢的东西。由于Reader
应用与Reader
monad相同,我们可以尝试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) a
或Free ((->) r) a
更直接地检查。