Haskell,ask的参数
你能通过询问得到什么参数吗? 我们经常可以看到Haskell,ask的参数,haskell,monads,Haskell,Monads,你能通过询问得到什么参数吗? 我们经常可以看到ask>>=f 这意味着ask>>=f=(\k->f(ask)k) 所以ask必须能够从环境中获得k函数。 然而,在文档中它是这样写的:ask::mr。 我错在哪里?类型为ma的值,其中m是单子,可以被认为是“单子动作”。因此,ask不接受任何参数,它只是一个值,您可以绑定(>=)从读卡器monad中提取一些值 查看Control.Monad.Trans.Reader中ReaderT的ask定义: -- | Fetch the value of th
ask>>=f
这意味着ask>>=f=(\k->f(ask)k)
所以ask必须能够从环境中获得k函数。
然而,在文档中它是这样写的:
ask::mr
。
我错在哪里?类型为
ma
的值,其中m
是单子,可以被认为是“单子动作”。因此,ask
不接受任何参数,它只是一个值,您可以绑定(>=
)从读卡器monad中提取一些值
查看Control.Monad.Trans.Reader中ReaderT
的ask
定义:
-- | Fetch the value of the environment.
ask :: (Monad m) => ReaderT r m r
ask = ReaderT return
ReaderT
只是一个数据构造函数,其中包含r->ma
类型的值,因此ReaderT return
是ReaderT rm
类型的值,它包含一个函数,return
(monadm
)
换句话说,ask
这里有一个“一元动作”,它提取读取器中存储的值
ask >>= f
那是
(ReaderT return) >>= f
使用Reader的>=
定义,我们得到:
ReaderT $ \ r -> do
a <- runReaderT (ReaderT return) r
runReaderT (f a) r
因此,它传递存储的值以决定下一个操作,也传递该值以便下一个操作可以像以前一样读取它
(如果不清楚,可以找一本读者教程)这是阅读器
单子。最终,最好的答案就是研究它的实现,在最简单的版本中(没有monad转换器,没有类)可以这样定义:
newtype Reader r a = Reader { runReader :: r -> a }
这是一个newtype
声明,因此Reader ra
只是函数类型r->a
的一个“重新标记”(可以这么说)<代码>询问
的定义如下:
ask :: Reader r r
ask = Reader (\r -> r)
这意味着ask
是一个重新标记的标识函数——该函数只返回自己的参数。如果我们使用runReader
操作向其提供值,我们可以看到这一点:
ghci> runReader ask 5
5
ghci> runReader ask "Hello world!"
"Hello world!"
这看起来不是很有用,但神奇之处在于Reader
有Functor
、Applicative
和Monad
的实例:
instance Functor (Reader r) where
fmap f (Reader g) =
-- A `Reader` that applies `f` to the original `Reader`'s results
Reader (\r -> f (g r))
instance Applicative (Reader r) where
pure a =
-- A `Reader` that ignores its `r` argument and just produces
-- a fixed value.
Reader (\_ -> a)
Reader ff <*> Reader fa =
-- A `Reader` that "combines" two `Reader`s by feeding the same
-- `r` value to both, and then combining their results
Reader (\r -> ff r (fa r))
instance Monad (Reader r) where
return = pure
Reader fa >>= k =
-- A `Reader` that feeds the same `r` both to the original one
-- and to the one computed by the `k` function
Reader (\r -> k (fa r) r)
实例函子(读取器r),其中
fmap f(读卡器g)=
--将“f”应用于原始“Reader”结果的“Reader”
读卡器(\r->f(gr))
实例应用程序(读卡器r),其中
纯a=
--忽略其'r'参数而只产生
--固定值。
读卡器(\\->a)
读卡器ff读卡器fa=
--一种“读取器”,通过给同一个读取器喂食而“结合”两个“读取器”
--'r'值,然后将它们的结果合并
读卡器(\r->ff r(fa r))
实例Monad(读取器r)其中
返回=纯
读卡器fa>>=k=
--将同一个“r”和原“r”同时输入的“Reader”
--和由'k'函数计算的值
读卡器(\r->k(far)r)
如果您研究这些,您会注意到Reader
所涉及的是延迟程序的点,您将包装器r->a
函数应用于r
。通常,如果您有一个类型为r->a
的函数,并且希望获得类型为a
的值,则必须为该函数提供类型为r
的参数。Reader
类实例允许您提前提供用于操作a
的函数,然后在最后提供r
ReaderT
类型和monawarder
类(具有ask::monawarder rm=>mr
方法)只是此方法的更高级版本。“ask>=f=(\k->f(ask)k)
”这是错误的。请告诉我正确的等式。我在这里发现了其他答案必须纠正等式。r在\r中是什么意思?@HaskellFun您是在问语法\r->…
是什么意思,还是在问r
参数代表什么?代表什么。我知道这个语法,只有lambda:),所以应该是这样的:ask>>=f=Reader(\r->f(ask r)r)=Reader(\r->f(r)r)
ghci> runReader ask 5
5
ghci> runReader ask "Hello world!"
"Hello world!"
instance Functor (Reader r) where
fmap f (Reader g) =
-- A `Reader` that applies `f` to the original `Reader`'s results
Reader (\r -> f (g r))
instance Applicative (Reader r) where
pure a =
-- A `Reader` that ignores its `r` argument and just produces
-- a fixed value.
Reader (\_ -> a)
Reader ff <*> Reader fa =
-- A `Reader` that "combines" two `Reader`s by feeding the same
-- `r` value to both, and then combining their results
Reader (\r -> ff r (fa r))
instance Monad (Reader r) where
return = pure
Reader fa >>= k =
-- A `Reader` that feeds the same `r` both to the original one
-- and to the one computed by the `k` function
Reader (\r -> k (fa r) r)