不像其他不安全*操作,文档的unsafeInterleaveIO是不是其可能存在的缺陷非常明显的.那么到底什么时候不安全?我想知道并行/并发和单线程使用的条件.
更具体地说,以下代码中的两个函数在语义上是等价的吗?如果没有,何时以及如何?
joinIO :: IO a -> (a -> IO b) -> IO b
joinIO a f = do !x <- a
!x' <- f x
return x'
joinIO':: IO a -> (a -> IO b) -> IO b
joinIO' a f = do !x <- unsafeInterleaveIO a
!x' <- unsafeInterleaveIO $ f x
return x'
Run Code Online (Sandbox Code Playgroud)
以下是我在实践中如何使用它:
data LIO a = LIO {runLIO :: IO a}
instance Functor LIO where
fmap f (LIO a) = LIO …Run Code Online (Sandbox Code Playgroud) 我从真实世界的 Haskell 中读到
它的操作如下:当一个
seq表达式被求值时,它会强制求值它的第一个参数,然后返回它的第二个参数。它实际上对第一个参数没有任何作用:seq仅作为强制评估该值的一种方式存在。
我在那里强调了then因为对我来说它意味着两件事发生的顺序。
从Hackage我读到
seq a b如果a是底部,则的值是底部,否则等于b。换句话说,它将第一个参数评估a为弱头部范式(WHNF)。seq 通常用于通过避免不必要的懒惰来提高性能。关于求值顺序的注意事项:表达式
seq a b不保证a会在 之前求值b。by 给出的唯一保证seq是两者a和b将在seq返回值之前进行评估。特别是,这意味着b可以在 之前进行评估a。[…]
此外,如果我# Source从那里点击链接,页面不存在,所以我看不到seq.
这似乎与此答案下的评论一致:
[…]
seq不能在普通的 Haskell 中定义
另一方面(或在同一方面,真的),另一条评论写道:
“真实”
seq在 GHC.Prim 中定义为seq :: a -> b -> b; …
haskell functional-programming lazy-evaluation order-of-execution weak-head-normal-form
我以为我很好地理解了惰性,直到我想出了下面的代码,它产生了一个<<loop>>错误。
weird = ([1],[2]) <> weird
main = print (head $ fst weird)
Run Code Online (Sandbox Code Playgroud)
直观上,我认为 Haskell 会这样做:“我需要 的第一个元素weird。而且我需要第一个元素的头。所以我需要计算。现在我从对的半群实例中fst weird知道(或者我是吗??) fst weird = [1] ++ fst weird. 太好了,我该回来了1”
我哪里弄错了?
我正在查看一些示例Fibonacci序列clojure代码:
(def fibs (lazy-cat [1 2] (map + fibs (rest fibs))))
Run Code Online (Sandbox Code Playgroud)
我一般都明白发生了什么,但不明白lazy-cat.我知道这lazy-cat是一个宏,正在翻译成这样的东西:
(def fibs (concat (lazy-seq [1 2]) (lazy-seq (map + fibs (rest fibs)))))
Run Code Online (Sandbox Code Playgroud)
究竟是什么lazy-seq实现的?即使没有,它仍会被懒惰地评估lazy-seq?这是否严格用于缓存目的?
编辑:谢谢你的答案.令我感到困惑的是,它与concatREPL中的一个普通模式一起工作,因为我之前已经在范围内绑定了fibs.
我不明白Call-by-name和Call-by-need之间的差异.据我所知,Call-by-need方法恢复了返回的答案.但它如何帮助我们,结果之间是否存在根本差异?
例如,
begin integer n;
procedure foo(e, n);
integer e, n;
begin
for n := 1 step 1 until 10 do begin
prints(`;;; the value of e is ');
printnln(e)
end
end;
foo(2 * n, n)
end
Run Code Online (Sandbox Code Playgroud)
因此,按照我的理解,在按名称呼叫时,我们将获得:
;;; the value of e is 2
;;; the value of e is 4
;;; the value of e is 8
Run Code Online (Sandbox Code Playgroud)
等等.这是因为我们通过2*n对e,并e与新的评估i每次.在需要召唤时会发生什么?
来自维基百科:
懒惰的评价是:
在编程语言理论中,延迟评估或按需调用是一种评估策略,它延迟表达式的评估,直到需要它的值
短路评估是:
短路评价,最小评估,或麦卡锡评价表示在将第二个参数时,才执行或评价一些编程语言一些布尔运算符的语义如果第一参数不足以确定表达式的值
那么它们之间有什么区别,例如当我有:
if(false && true && true) {
//boo
}
Run Code Online (Sandbox Code Playgroud)
据我所知,编译器之后不会执行表达式,false因为我已经完成&&了整个表达式false.(对?)
这种行为称为懒惰评估还是短路评估?
这个答案是什么(斯卡拉的懒惰val)的(隐藏)成本?展示了它们是如何在Scala 2.7中实现的.但正如评论所说,从那以后这一定已经发生了变化,所以我很好奇,类lazy val变量的当前(2.10)实现是什么?
如果我将此常量pascal定义为
pascal :: [[Int]]
pascal = iterate newrow [1]
where newrow = (zipWith (+) <*> tail) . ([0]++) . (++[0])
Run Code Online (Sandbox Code Playgroud)
我pascal !! 50 !! 50在GHCI中评估,这个三角形的大部分是什么?这种懒惰是否意味着只计算必要的值(加上一堆thunk)?
在Haskell中,是否可以测试一个值是否已被评估为弱头正常形式?如果一个函数已经存在,我希望它有一个像这样的签名
evaluated :: a -> IO Bool
Run Code Online (Sandbox Code Playgroud)
有一些类似功能的地方.
一个以前的答案给我介绍:sprintghci的命令,该命令将打印已经被迫弱头部正常形态的值只有部分.:sprint可以观察是否已评估某个值:
> let l = ['a'..]
> :sprint l
l = _
> head l
'a'
> :sprint l
l = 'a' : _
Run Code Online (Sandbox Code Playgroud)
有可能IO检查本来是禁止的属性.例如,可以比较IO以查看两个值是否来自同一声明.这是由StableNames in提供System.Mem.StableName并用于解决数据统一中的可观察共享问题.相关内容StablePtr未提供检查引用值是否为弱头正常形式的机制.
seq功能文档说明如下:
关于评估顺序的注释:表达式
seq a b不保证a将在之前进行评估b.给出的唯一保证seq是,既a和b会前进行评估seq返回一个值.特别是,这意味着b可以在之前进行评估a.如果需要保证特定的评估顺序,则必须使用pseq"并行"软件包中的功能.
所以我有一个sum带累加器的懒函数:
sum :: Num a => [a] -> a
sum = go 0
where
go acc [] = acc
go acc (x:xs) = go (x + acc) xs
Run Code Online (Sandbox Code Playgroud)
显然,这在大名单上非常缓慢.现在我用seq以下方法重写这个函数:
sum :: Num a => [a] -> a
sum = go 0
where
go acc [] = acc
go acc (x:xs) = …Run Code Online (Sandbox Code Playgroud) lazy-evaluation ×10
haskell ×6
ghc ×2
algorithm ×1
clojure ×1
evaluation ×1
fibonacci ×1
scala ×1
scala-2.10 ×1
terminology ×1
thunk ×1
variables ×1