2017-11-29 9 views
1

こんにちは私は初心者ですし、私はハスケルで再帰を学ぼうとします しかし、私の再帰関数は私に解決策を与えると私のPCはフリーズしません。ここに私の機能があります。私の関数は数値を取得し、1で減算します。 数値が減算されるたびに、0から始まるリストに追加されます。たとえば、 we 3 = [0,3,2,1]ハスケル私の再帰クラッシュ

唯一、現在お使いのプログラムがフリーズした理由ですが
we w 
    |w == 0 = [] 
    |w >0 = te [0] w w 
    |w <0 = error "test" 
    |otherwise = error "test" 
    where 
te (x:xs) f c = te (x:f:xs) (f-1) (c-1) 
te (x:xs) f 0 = x:xs 
te (x:xs) 0 c = x:xs 
te (x:xs) 0 0 = x:xs 
+2

よく、最初のパターンの 'te'は常に一致するので、* list *を大きくしておきます。 –

+0

どのように再帰を止めることができますか?f 0 0 cと0 0 – EStudent

+0

底部の代わりに 'te'定義の最上位を指定します。それは "最も特定の機能が呼び出される" Javaのようなものではありません。ハスケルは、これらの火災の1つが発生するまで、上から下に句を概念的に評価する。 –

答えて

4

あなたの関数は、いくつかの問題があります。

  1. te (x:xs) f c = ...ほぼあらゆる可能性をマッチするパターンです:最初の引数を持つすべての呼び出しは、非ています空リストは一致し、残りの句は決して「発火」しません。これらは第1節のサブセットパターンであるためです。
  2. 最初の句を取るときに、増加しているリストで再帰を実行します。 (最初の項目のために)基本ケースに入る方法はありませんが、最終的にはメモリが足りなくなります。

いくつかの奇妙な(間違っていないですが、効率的でエレガントではない)あなたの機能を持つものもあります。

  1. あなたはte機能でfcを使用しますが、これらは常に同じを持っているが、値;
  2. w > 0,w < 0w == 0と比較してください。それ以外の場合は、値がそれ以上ではなく、等しくないことがないため、これは奇妙です。

おそらく、私たちは最初に描画ボードに戻る必要があります。我々は機能weを定義し、我々は3例を区別:

we w | w > 0 = ... 
    | w == 0 = ... 
    | otherwise = ... 

明らかに(これはあなたが投稿の仕様ではありません)、私たちはw < 0にエラーすべき、とリターンの最初のステップは、良いもの、多かれ少なかれです場合wでは空リストはそう、ゼロに等しいです:

we w | w > 0 = ... 
    | w == 0 = [] 
    | otherwise = error "w is less than zero" 

は今w > 0のために、我々は他の何かが続い0で始まるリストを生成しますので、私たちは書くことができます知っている:

we w | w > 0 = 0 : ... 
    | w == 0 = [] 
    | otherwise = error "w is less than zero" 

したがって、0を先頭にしてリスト(_:_)を作成します。今、残りは(例えばte用)再帰関数の呼び出しです:n > 0、私たちは「を発する」n、およびデクリメントに再帰を行う、その場合には:

we w | w > 0 = 0 : te w 
    | w == 0 = [] 
    | otherwise = error "w is less than zero" 
    where te n = ... 

teのために2つの可能性がありますn;またはケースn <= 0には、我々は(私たちは空のリストを生成)終了:

we w | w > 0 = 0 : te w 
    | w == 0 = [] 
    | otherwise = error "w is less than zero" 
    where te n | n > 0 = n : te (n-1) 
       | otherwise = [] 

と、それはそれです!

関連する問題