我无法理解这一点:
假设t被隐藏一个读者单子里面。
我可以使用ask:
do
x <- ask
...
Run Code Online (Sandbox Code Playgroud)
它将 隐藏的值解包为x
现在我试图了解>>=会做什么,但我很挣扎。
你能向我解释一下吗?
这是我的尝试:
f = \x -> x
ask >>= (\x -> return x)
= Reader $ \r -> f (ask (r)) r
{ using the fact that ask is identity }
= Reader $ \r -> f(r) r
Run Code Online (Sandbox Code Playgroud)
但是,我不明白这是如何达到隐藏 值的
我认为主要的一点是,里面真的没有任何隐藏的东西Reader- 相反它是一个函数 -当你运行阅读器时你的隐藏值进入了阶段(这是当你向阅读器显示你的隐藏值并让它评估一些输出)。
好吧,让我们稍微简化一下,并假设我们的ReaderMonad的结构定义如下:
data Reader h a = Reader { run :: h -> a }
Run Code Online (Sandbox Code Playgroud)
这意味着您隐藏的值将具有某种类型h,并且Reader它只是一个函数,a当出现这样的值时,它会产生一些其他值(类型)。
正如你可以看到有没有隐藏在所有的价值-你当自己提供它运行的Reader有run
下面是一个例子:
showInt :: Reader Int String
showInt = Reader show
Run Code Online (Sandbox Code Playgroud)
你会像这样使用它
?> run showInt 5
"5" -- has type :: String
Run Code Online (Sandbox Code Playgroud)
Monad 实例基本上就是这个(你必须为Applicativeand提供实例Functor,我将跳过)
instance Monad (Reader h) where
return v =
Reader (const v)
r >>= f = Reader $ \ h ->
let v = run r h
r' = f v
in run r' h
Run Code Online (Sandbox Code Playgroud)
请注意您如何再次等待有人为您提供h(通过调用run),然后:
v使用读取器获取值run r hv来获得另一个读者f'h:run r' hask正如你所说:它只是读者使用id- 它会在运行时重现给定的值:
ask :: Reader h h
ask = Reader id
Run Code Online (Sandbox Code Playgroud)
现在我们终于可以解决这个问题了:
如果我们跑会发生什么
let r = ask >>= (\x -> return x)
Run Code Online (Sandbox Code Playgroud)
好吧,让我们在:
run r "Hello"
{ def r }
= run (ask >>= return) "Hello"
{ def >>= }
= run (\h ->
let v = run ask h
r' = return v
in run r' h) "Hello"
{ def run: plug "Hello" into h }
= let v = run ask "Hello"
r' = return v
in run r' "Hello"
{ ask = Reader id - so run ask "Hello" = "Hello" -> v = "Hello" }
= let r' = return "Hello"
in run r' "Hello"
{ simplify }
= run (return "Hello") "Hello"
{ r' = const "Hello" = \ _ -> "Hello" }
= (\ _ -> "Hello") "Hello"
{ apply }
= "Hello"
Run Code Online (Sandbox Code Playgroud)
顺便说一句:它以这种方式解决是一件好事,因为其中一个 monad-laws(它应该成立但不是由 Haskell 强制执行)指出:
m >>= return == m
Run Code Online (Sandbox Code Playgroud)
这意味着在这里,您的读者 ask >>= return == ask
这会让这一切变得更容易;)