コードのこの部分は Haskell の範囲です
[test n .. test (n-1)]
範囲は、左の数字と右の数字を計算し、左の数字から右の数字までのすべてのステップを含むリストを作成することによって機能します。そう:
[1 .. 6] --> [1,2,3,4,5,6]
[5 .. 9] --> [5,6,7,8,9]
ご覧のとおり、デフォルトのステップは 1 であるため、左の数値が右の数値よりも大きい場合、空のリストが得られます。
[4 .. 3] --> []
余談ですが、別の番号を指定してデフォルトのステップをオーバーライドできます。
[1, 3 .. 6] --> [1,3,5] -- step is 2
[8, 6 .. 3] --> [8,6,4] -- step is -2
ご覧のとおり、ステップ サイズが 1 以外の場合は、結果のリストに含まれるものに注意する必要があります。これは特に負のステップの場合に当てはまり、 のような整数でないステップがある場合はなおさらです[1, 1.25, .. 2.1]
。範囲を使用して非整数のリストを生成することはほとんどありません。
あなたのソリューションには、次の行があります
test n = sum[test n .. test (n-1)]
範囲の規則によれば、これはうまくいかないはずです。プログラムが範囲からリストを作成しようとすると、それがtest n
範囲の左の数であるため、計算が試みられます。しかし、test n
この行全体が最初に計算しようとしているものなので、それではどこにも行きません。そのため、無限ループが発生し、プログラムがハングします。
あなたはやろうとすることができます
test n = sum[1 .. test (n-1)]
それはあなたが与えた例に近いようです。1
(これはtest 1
) で始まり、 で終わりますtest (n-1)
。しかし、問題はその中間の値です。範囲には 1 のステップがあるため、最終的には次のようになります。
[1 .. test (n-1)] --> [1,2,3, ......., test (n-1)]
と同じではありません
[test 1, test 2, test 3, .... , test (n-1)]
また、範囲は一定のステップしか持てないため、デフォルトのステップをオーバーライドしたとしても、単純な範囲でこの最後の行を取得する方法はありません。これを解決するためのヒントの 1 つは、リスト内の要素の数に注目することです。
length [1 .. test (n-1)] --> test (n-1),
-- because [1,2,3] has 3 elements, [1,2,3,4] has 4 and so on
length [test 1, test 2, test 3, ....... , test (n-1)] --> n-1
-- this is not quite Haskell syntax
ここでの Haskell のやり方は、正しい数の要素を持つリストを作成し、それを変換して各要素が正しいものになるようにすることです。(n-1)
要素のリストをどのように作成しますか? 単純:
[1..(n-1)]
ここから、いくつかの方法で行くことができます。luqui からのリスト内包表記があります。
[test x | x <- [1..(n-1)]]
これは、各数値を範囲から取り出して に代入し、関数をにx
適用すると考えることができるため、 が得られます。別の方法は、次の関数を使用することです。test
x
[test 1, test 2, test 3, ....... , test (n-1)]
map
map test [1..(n-1)]
私はこれをtest
リストの各要素に同時に適用すると考えていますが、これはリスト内包表記とまったく同じものであり、2 つの見方があります。どちらの方法でも[1..(n-1)]
範囲を使用することに注意してください。
[test n .. test (n-1)]
元のコードの範囲の代わりにこれらのいずれかを使用すると、ソリューションに非常に近くなります。luqui が指摘するように、足りないのは 1 を足すことだけです。