我只是在学习Haskell和IO monads.我想知道为什么这不会强制程序输出"hi"以及"bye":
second a b = b
main = print ((second $! ((print "hi") >>= (\r -> return ()))) "bye")
据我所知,$!运算符会强制要求第一个参数second进行求值,并且>>=运算符需要运行print "hi"以便从中获取值并将其传递\r -> return ()给屏幕,这将打印"hi"到屏幕.
我的推理有什么问题?
而且,有没有办法证明Haskell不能被欺骗(除了使用不安全的函数)在"安全"代码中运行IO操作?
鉴于:
?: let f = putStrLn "foo" in 42
42
什么是f类型?为什么"foo"在显示结果之前没有打印42?
最后,为什么以下不起作用?
?: :t f
<interactive>:1:1: Not in scope: ‘f’
为了在函数上下文中获得顺序计算,在 JavaScript 中,我经常使用
const right = a => b => b;
const f = () => right(console.log("hi"))(true);
console.log(f());这有点类似于do线程,并且实现起来更简单,但仅适用于急切求值的语言,例如 JavaScript。
在 Haskell 中,由于该语言以惰性求值/按需调用的方式工作,因此 的参数a将不会被求值,因为 lambda 表达式体中不需要它。
所以,我想知道什么是简单的智能方法来实现right在惰性求值中起作用的函数。 <- 这是我的第一个问题。
有 Haskell wiki 文章:
根据 Haskell 2010 报告,该
seq原语尽管有其名称,但不需要以某种预定义的顺序评估其参数。对于并行编程,有时需要使用 seq 的变体来进行这样的排序:
虽然我们主要关注实现,但我们的工作对编程模型产生了一些影响:我们确定了对 pseq 和 seq 的需求(第 2.1 节),并且我们隔离了编写并行程序的“策略”方法中的一个重大困难(第 7 节)。对多核 Haskell 的运行时支持;西蒙·马洛、西蒙·佩顿·琼斯和萨特南·辛格。不是两个或多个具有相似目的的相似原语,而是使用其参数的传统评估顺序来扩展现有的 seq 原语 - 首先,然后第二;简单严格控制的角色由具有更合适名称的新原语执行,例如
amid,在没有排序或混乱的严格性中。
和
由于 Haskell 2010 报告没有指定关于其参数的任何计算顺序,因此原语的名称
seq :: a -> b -> b是用词不当。
引入原语 …