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
(monad
m

换句话说,
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)