假设:
Prelude> import Control.Parallel.Strategies
Prelude> import Control.Parallel
Prelude> let fact n = if (n <= 0) then 1 else n * fact (n-1) :: Integer
Prelude> let xs = map (runEval . (\x -> return x :: Eval Integer) . fact) [1..100]
Prelude> let ys = map fact [1..100]
Prelude> :sprint xs
xs = _
Prelude> :sprint ys
ys = _
据我了解,xs
处于弱头范式。这是为什么? runEval
是否对将值/计算带到普通表单有任何影响?
答案 0 :(得分:2)
原因是let
只是将一个名字与一个表达式绑定,但它不会触发对表达式的任何评估。
为了更好地理解,让我使用一个更简单的例子
Main> let x = error "foobar!" in 1
1
正如您所看到的,应该抛出应该抛出异常的error "foobar!"
。原因是没有使用x
,因此Haskell没有对其进行评估。您需要触发评估x
Main> let x = error "foobar!" in x `seq` 1
*** Exception: foobar!
回到您的示例,请注意Eval x
指定如何评估x,而不是在程序中评估它的时间。
请查看Lazyness上的这篇wiki文章了解更多信息。