Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么这个Haskell语句没有惰性地进行评估?_Haskell_Lazy Evaluation_Ghci - Fatal编程技术网

为什么这个Haskell语句没有惰性地进行评估?

为什么这个Haskell语句没有惰性地进行评估?,haskell,lazy-evaluation,ghci,Haskell,Lazy Evaluation,Ghci,我定义了以下函数: ex 1 x = 1 ex 0 x = 0 ex b x = b ** x 然后,当我执行以下操作时: 1 `ex` (sum [1..]) 它尝试计算无限序列的和,而不是懒惰并返回1。为什么? 编辑:进一步调查后,我发现,如果我在文件中定义ex函数,就会发生懒惰,但如果我在GHCI中定义它,则不会发生懒惰: $ ghci GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help Loading pack

我定义了以下函数:

ex 1 x = 1
ex 0 x = 0
ex b x = b ** x
然后,当我执行以下操作时:

1 `ex` (sum [1..])
它尝试计算无限序列的和,而不是懒惰并返回1。为什么?


编辑:进一步调查后,我发现,如果我在文件中定义
ex
函数,就会发生懒惰,但如果我在GHCI中定义它,则不会发生懒惰:

$ ghci
GHCi, version 6.8.2: http://www.haskell.org/ghc/  :? for help
Loading package base ... linking ... done.
Prelude> let ex 1 x = 1
Prelude> let ex b x = b ** x
Prelude> ex 1 (sum [1..])
<interactive>: out of memory (requested 1048576 bytes)

那么,新的问题是为什么?

我忽略了一点懒惰,这使得下面的答案是错误的


因为
sum
计算序列中所有元素的总和。对你来说,这是无止境的

你可能想要

map ((curry ex) 1) [1..]
就是

map -- map each item x to y
    (
        (
            curry ex -- curry ex, to transform (x, y) -> z into x -> y -> z
        )
        1 -- then invoke it with 1, which results in y -> z, x being 1
    )
    [1..] -- the infinite sequence to be mapped.

在GHCi中,每个
let
语句都引入了
ex
的新定义,而不是您所期望的多个模式情况。因此它会挂起,因为当您随后输入
ex1(sum[1..])
时,只有最终的
exbx=b**x
版本存在

如果要在GHCi中定义具有多个模式案例的函数,则需要将其放在单个
let
语句中,如下所示:

let ex 1 x = 1; ex 0 x = 0; ex b x = b ** x
f x = do
    y <- get
    put (x + y)
    return y
这同样适用于通常跨多行写入的任何其他内容,例如
do
notation。例如,这样的函数:

let ex 1 x = 1; ex 0 x = 0; ex b x = b ** x
f x = do
    y <- get
    put (x + y)
    return y
fx=do
Y
这里没有用两种情况定义函数。使用一个大小写定义函数,然后再次定义它,以覆盖以前的定义


要使用两种模式定义一个函数,请使用
让ex1x=1;ex b x=b**x
,即用分号分隔大小写。

否,1
ex
(总和[1..])在我的计算机上返回1.0。什么版本的ghc等。?对于ex1(sum[1..]),你得到了同样的结果吗?@shrevatsar:好的观点,请看我上面的更新。啊哈,这真的很不方便。很高兴知道,谢谢@perimosocordiae:作为GHCi的一个相当大的用户,我通常习惯于将我的大部分或全部定义写入一个外部文件,用GHCi加载该文件,使用REPL主要用于计算简单表达式。您也可以使用
:set+m
在多行上编写定义。@aleator:我相信这是一个比本文更新的功能。考虑到更新的GHC功能和库,我现在有多少答案是愚蠢的,我不寒而栗。-1:它只会在实际需要的情况下评估总和,在这种情况下它不是。
Prelude> let ex 1 x = 1
Prelude> let ex b x = b ** x