2006-06-16
■ 1から10までの和 その2
mysum :: Int -> Int mysum 1 = 1 mysum x = x + mysum (x-1) main = print $ mysum 10
上のコードの3行目の括弧をはずしコンパイル後、生成された実行ファイルを実行するとエラーが出ます。
mysum :: Int -> Int mysum 1 = 1 mysum x = x + mysum x-1 --括弧をはずしてコンパイル main = print $ mysum 10
--実行時エラー Stack space overflow: current size 8388608 bytes. Use `+RTS -Ksize' to increase it.
なんでだろう(^_^;)
■ どちらが大きい?
フツケルP174のガードを使って、二つの整数xとyに関して、xがyより大きい時は、x is greater than yと表示し、xがyより小さい時はx is less than yと表示されるコードを書いてみました。
mysum :: Int -> Int -> String mysum x y | x > y = "x is greater than y" | x < y = "x is less than y" main = putStrLn $ mysum 2 100
--実行結果 x is less than y
main = putStrLn $ mysum 2 100を手動デバッグ
mysum 2 100
x = 2,y = 100
最初の条件文の評価:x > y => false 次の条件文へ進む
次の条件文の評価:x < y => True "x is less than y"という文字列を呼び出し元へ返す
main = putStrLn "x is less than y"
"x is less than y"という文字列にputStrLn関数を適用したので、コンソールに"x is less than y"という文字列が表示される。
■ 1から10までの和 その1
1から10までの和を求める方法を、id:muscovyduckさんに教えて頂いたので早速試してみました。
mysum :: Int -> Int mysum 1 = 1 mysum x = x + mysum(x-1) main = print $ mysum 10
手動でデバッグしてみました。
mysum 10 = 10 + mysum(10 - 1)
10 + (mysum 9)
10 + (9 + mysum 8)
(10 + 9) + (mysum 8)
(10 + 9) + (8 + mysum 7)
(10 + 9 + 8) + mysum 7
(10 + 9 + 8) + (7 + mysum 6)
(10 + 9 + 8 + 7) + mysum 6
(10 + 9 + 8 + 7) + (6 + mysum 5)
(10 + 9 + 8 + 7 + 6) + mysum 5
(10 + 9 + 8 + 7 + 6) + (5 + mysum 4)
(10 + 9 + 8 + 7 + 6 + 5) + mysum 4
(10 + 9 + 8 + 7 + 6 + 5) + (4 + mysum 3)
(10 + 9 + 8 + 7 + 6 + 5 + 4 ) + mysum 3
(10 + 9 + 8 + 7 + 6 + 5 + 4 ) + (3 + mysum 2)
(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3) + mysum 2
(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3) + (2 + mysum 1)
(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 ) + mysum 1
(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 ) + 1
10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1
==> 55
mysum x = x + mysum x-1
では、
mysum x = x + (mysum x) - 1
と、同じ結果になってしまいます
mysum x = x + mysum $ x -1
なら、うまくいくと思いますよ
は型エラーになります.$は優先順位が0の関数なので
mysum x = (x + mysum) $ (x -1)
と同じことになります。
アドバイス頂いたとおり以下のようにコードを修正しましたが、依然としてエラーが出ています。
mysum :: Int -> Int
mysum 1 = 1
mysum x = x + mysum $ x -1
main = print $ mysum 10
<上のコードをコンパイルしたときに表示されたエラー>
Expecting a function type, but found `a'
Expected type: Int
Inferred type: Int -> Int
In the second argument of `(+)', namely `mysum'
In the first argument of `($)', namely `x + mysum'
因みにmysum関数のところのみを修正した以下のコードもコンパイルしてみました。
mysum :: Int -> Int
mysum 1 = 1
mysum x = (x + mysum) $ (x-1)
main = print $ mysum 10
<実行したときに表示されたエラー>
Expecting a function type, but found `a'
Expected type: Int
Inferred type: Int -> Int
In the second argument of `(+)', namely `mysum'
In the first argument of `($)', namely `(x + mysum)'
二つのエラーを見比べてみると
In the first argument of `($)', namely `(x + mysum)'
この箇所の(x + mysum)の括弧の有無を除けば同じエラーが表示されていますね。
フツケルの153ページあたりも後ほど読んでみたいと思います(^^)
いえ、そうではなくて‥‥。
taninswさんは、次のことをおっしゃっているのだと思います。
・「mysum x = x + mysum $ x -1」と書くと「型エラーになります」。
・なぜなら、「mysum x = (x + mysum) $ (x -1)」と解釈されるからです。
というわけで「mysum x = x + mysum $ x -1」も「mysum x = (x + mysum) $ (x -1)」もダメで、「mysum x = x + mysum (x - 1)」と書かないとうまく動かないのです。
すいません、言葉足らずでした。