1

当我使用 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

我想让一个结果getLineinto a

更新2

我记下这段代码,以供像我这样的人以后参考。在@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        
4

3 回答 3

2

您的 JS 代码将转换为 Haskell:

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

您的 JS 函数没有任何内容(您可以将其建模为 () 类型)并且什么也不返回,即再次 ()

getLine是类型的值,IO String所以如果你说let a = getLinea就变成类型的值IO String。您想要的是从中提取StringIO String可以这样做:

a <- getLine

于 2013-10-09T09:44:45.307 回答
0

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

要引入严格性,您可以使用seq,它接受两个参数,第一个是严格评估的,第二个是返回的。阅读更多

这是该页面中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只是丢弃了其第一个参数的值。

于 2013-10-09T09:12:53.430 回答
0
  1. Haskell是非严格的,不是懒惰的。
  2. 许多表达式将被严格评估,请参见此处,因此您通常可以简单地通过代码结构强制执行严格性。
  3. 在 Haskell 中,如果c有一个与返回类型匹配的类型 - 值 -a()然后将分配给它(从不是函数本身)。
  4. Haskell 可能会推迟计算,直到您的代码真正需要 的值,c但在大多数情况下您不应该关心。

为什么要强制提前评估?通常,在 Haskell 中这样做的唯一原因是性能。在不太纯粹的语言中,您可能依赖于副作用,但在 Haskell 中并非如此 - 除非您正在使用 IO monad 并且它为您提供了强制顺序评估所需的一切。

更新啊,所以你正在使用IO

于 2013-10-09T09:19:12.273 回答