【发布时间】:2017-10-08 17:22:53
【问题描述】:
我将在底部用示例重申我的问题。
当我说m 或k 时,我指的是函数调用中的左右值m >>= k。
对 monad 的理解有些模糊。如果m 是一个计算并且k 是一个lambda 表达式,这是否意味着k 有两个用途,它可以使用它来处理do 块中的绑定,也可以在Monad 实例中用于其他用途定义?如果一个值在 k 在其 do 块中被评估之前绑定,值会自动传递给它还是 Monad 实例方法定义,我们定义传播到 k 的唯一效果?
我看到的例子可能有点误导我在解释 monad 时总是将前一个绑定项直接传递给 lambda 表达式。即使使用的符号是pure-do-no-lambda,它是否总是传递给隐藏的lambda的最后一个绑定项,在引擎盖下。现在,使用带有多个参数的 lambda 并将其用作 m >>= k 中的 k 是不好的做法吗?或者我假设如果我们在 do 块中工作,在幕后,只有一个参数被传递给下一个“隐藏”的 lambda 表达式并且这个参数是之前直接绑定的项目,我错了吗?
我现在将用例子重申我的问题。
do
a <- getLine
b <- getLine
putStrLn $ a ++ b
a 和 b 绑定到从运行 getLine 返回的 IO 容器中的值。在引擎盖下,以下哪项是等效的(如果有的话)?
getLine >>= \a -> getLine >>= \b -> putStrLn (a ++ b)
或
getLine >>= \a -> getLine >>= \(a, b) -> putStrLn (a ++ b)
我们看到getLine 的IO 容器中的值被提取并传递给 lambda 表达式。
如果第一个是正确的,那不会导致错误,因为 a 将在 monad 定义中未定义?
我凭空取出了第二个。我没有看到任何证据表明它可能是这样,但即使它不是正确的答案,我们可以这样做吗?当然,在这种情况下,我们必须使与>>= 一起使用的所有 lambda 表达式都采用 2 元组。这种行为是否不仅仅由我们的>>= 定义决定,至少在使用 only-lambda-no-do 表示法时如此?
我们可以在 monad 定义中使用这个 lambda 表达式并传递一些东西给它,让它再次打印屏幕吗?我们应该吗?
如果我们想在>>= 定义中使用putStrLn,我们是否必须将一些任意值传递给k 才能得到putStrLn 函数?
谢谢。和平。
【问题讨论】:
标签: haskell lambda functional-programming monads