如何使用免费monads实现Reader? [英] How do I implement Reader using free monads?

查看:134
本文介绍了如何使用免费monads实现Reader?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,我已经知道如何使用 Reader (和 ReaderT ,未显示) a href =http://hackage.haskell.org/package/operational =noreferrer> 运营 包裹:

  { - #LANGUAGE GADTs,ScopedTypeVariables# - } 

导入Control.Monad.Operational

数据ReaderI ra其中
Ask :: ReaderI rr

类型阅读器ra =程序(ReaderI r)a

询问::读者rr
询问= singleton询问

runReader :: forall r a。阅读器r a - > r - > a
runReader = interpretWithMonad evalI
其中evalI :: forall b。 ReaderI r b - > (r - > b)
evalI Ask = id

但我无法计算我的生活如何做到这一点与免费monads(我使用爱德华Kmett的 免费 包)。我得到的最接近的是这个,我的理解是作弊((( - >)r)已经是单子):

  import Control.Monad.Free 

类型阅读器ra =免费(( - >)r)a

ask :: Reader rr
ask = Free Pure

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

- 或者更简单明了:
-
- > runReader =缩进

即使这不像我猜想的那样愚蠢,这不是我因为我想要的基本上是能够检查 Reader 作为数据...

解决方案

我不认为这是可以做的,除非他们有你的方式。但是,我不认为这对读者来说是独一无二的。考虑免费的monad版本的作家

  data WriterF ma = WriterF ma派生(Functor)

类型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 =>作家m a  - > (m,a)
runWriter(Pure a)=(mempty,a)
runWriter(Free x)= algebraWriter。 fmap runWriter $ x

同样,我认为免费阅读器为

 类型ReaderF r =( - >)r 

类型Reader r = Free(ReaderF r)

我喜欢这个,因为添加它们会给你状态monad



<$ p $ ((ReaderF x):+:(WriterF x))

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

请注意,您的操作解决方案可以与通过使用免费函子可以免费,就像运行时可以使用的任何东西一样

  data FreeFunctor fx = forall a。 FreeFunctor(fa)(a  - > x)

但是, FreeFunctor ReaderI 也同构于( - >)


Ok, so I have figured out how to implement Reader (and ReaderT, not shown) using the operational package:

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

But I can't figure out for my life how to do this with free monads (I'm using Edward Kmett's free package). The closest I've gotten is this, which I understand is cheating (something about how ((->) r) is already a 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

Even if this wasn't as dumb as I suspect it is, it's not what I want because what I want, basically, is to be able to inspect a Reader as data...

解决方案

I don't think it can be done except they way you have. But, I don't think this is unique to reader. Consider the free monad version of writer

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

type Writer m = Free (WriterF m)

obviously, WriterF is isomorphic to writer, but this does behave the way we would expect with the simple algebra

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

thus

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

Similarly, I think of the Free reader as

type ReaderF r = (->) r

type Reader r = Free (ReaderF r)

I like this, because adding them gives you the state 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

Note, that your operational solution could be made to work with Free by using the "free functor", as can anything that works with operational

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

but, that FreeFunctor ReaderI is also isomorphic to (->).

这篇关于如何使用免费monads实现Reader?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆