8

次の関数を定義しています。

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)

ex定義をファイル (この場合は test.hs)にプルすると、次のようになります。

$ ghci
GHCi, version 6.8.2: http://www.haskell.org/ghc/  :? for help
Loading package base ... linking ... done.
Prelude> :load test.hs 
[1 of 1] Compiling Main             ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> ex 1 (sum [1..])
1.0

では、新しい質問は、なぜですか?

4

3 に答える 3

17

GHCi では、期待される複数のパターン ケースではなく、各letステートメントが の新しい定義を導入します。後で入力すると、最終バージョンしか存在しないexため、ハングします。ex 1 (sum [1..])ex b x = b ** x

GHCi で複数のパターン ケースを持つ関数を定義する場合は、次のletように 1 つのステートメントに記述する必要があります。

let ex 1 x = 1; ex 0 x = 0; ex b x = b ** x

同じことは、記譜法など、通常は複数行にまたがって書かれるものにも当てはまりますdo。たとえば、次のような関数です。

f x = do
    y <- get
    put (x + y)
    return y

GHCi では次のように記述します。

let f x = do { y <- get; put (x + y); return y }
于 2010-07-08T17:55:56.787 に答える
1
Prelude> let ex 1 x = 1
Prelude> let ex b x = b ** x

ここでは、2 つのケースで関数を定義していません。1 つのケースで関数を定義してから、以前の定義をオーバーライドして再度定義します。

1 つの関数を 2 つのパターンで定義するにはlet ex 1 x = 1; ex b x = b ** x、 を使用します。つまり、大文字と小文字をセミコロンで区切ります。

于 2010-07-08T17:57:30.843 に答える
-2

怠惰の 1 つのポイントを逃したため、以下の答えが偽になります。


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.
于 2010-07-08T17:52:12.837 に答える