如何立即评估Haskell表达式?

时间:2013-10-09 08:57:03

标签: haskell evaluation strict

当我使用JS时,我有两个选项来处理函数。

var a = function() {};
var b = a;     // b is the function a itself.
var c = a();   // c is result of the evaluation of function a.

AFAIK,Haskell默认是懒惰的,所以默认情况下我总是得到b。但如果我想获得c,我该怎么办?

更新

我想我应该明确一词

我在ghci做了类似的事情。

let a = getLine
a

我想将getLine的结果导入a

UPDATE2

我注意到此代码供以后像我这样的人参考。 我可以用@ Ankur的帮助纠正Haskell的翻译。 上面的代码示例不是很好,因为函数a不会返回任何内容。 如果我这样改变它;

var a = function(x,y) { return x * y; };
var b = a;     // b is the function a itself.
var c = a();   // c is result of the evaluation of function a.

翻译成Haskell会变成这样。

let a = \ x y -> x* y    // Anonymous lambda function.
let b = a
let c = a 100 200        

3 个答案:

答案 0 :(得分:2)

您的JS代码将转换为Haskell:

Prelude> let a = (\() -> ())
Prelude> let b = a
Prelude> let c = a()

你的JS函数没有任何东西(你可以建模为()类型)并且没有返回任何内容,即()

getLineIO String类型的值,因此,如果您说let a = getLinea将成为IO String类型的值。你想要的是从String中提取IO String,可以这样做:

a <- getLine

答案 1 :(得分:0)

请注意,与Javascript的并行不太正确 - 例如,假设a返回一个数字,b + b在Haskell中有意义但在您的示例Javascript中没有意义。原则上Haskell中的函数只是一个参数的函数 - 看起来是两个参数的函数是一个参数的函数,它返回一个参数的函数,返回一个值。 Haskell中的b不是一个未经评估的“零参数函数”,而是一个未评估的值。

为了引入严格性,你可以使用seq,它有两个参数,第一个是严格评估的,第二个是返回的。 Read more

以下是该页面的示例,seq用于强制立即评估z'

foldl' :: (a -> b -> a) -> a -> [b] -> a
foldl' _ z [] = z
foldl' f z (x:xs) = let z' = f z x in z' `seq` foldl' f z' xs

注意z'之后再次使用的方式作为foldl'的第二个参数,因为seq只丢弃其第一个参数的值。

答案 2 :(得分:0)

  1. Haskell是non-strict,而不是懒惰。
  2. 将严格评估许多表达式,请参阅here,因此您通常可以仅使用代码结构强制严格。
  3. 在Haskell中,如果c的类型与返回类型匹配 - 值{ - a()那么那将是分配给它的(不是函数本身)。
  4. Haskell可能会推迟计算,直到您的代码实际需要c的值,但在大多数情况下您不应该关心。
  5. 为什么要提前强制进行评估?通常,在Haskell中执行此操作的唯一原因是性能。在不太纯粹的语言中,你可能会依赖于副作用,但在Haskell中不会出现这种情况 - 除非你正在使用IO monad,这样你就可以强制进行连续评估。

    更新啊,所以 使用IO