3

私はHaskellとプログラミング全般に不慣れです。nから一連のコラッツ数を生成する関数を定義しようとしています。私は持っている:

collatz n = (collatz' n) : 1
   where collatz' n = (takeWhile (>1) (collatz'' n))
          where collatz'' n = n : collatz'' (collatz''' n)
                 where collatz''' 1 = 1
                       collatz''' n = if (even n) then (div n 2) else ((3*2)+1)

これを GHCi で実行すると、次のエラーが発生します。

No instance for (Num [t])
  arising from the literal `2' at <interactive>:1:7
Possible fix: add an instance declaration for (Num [t])

これが何を意味するのかわかりません。問題は、リストに「1」を追加しているようです。この問題が発生する理由は

collatz' n = (takeWhile (>0) (collatz'' n))

正しい Collat​​z シーケンスに続く "1" の無限シーケンスを生成します。でも、

collatz' n = (takeWhile (>1) (collatz'' n))

nから"1" を除くすべてのコラッツ数を生成します。私は何を間違っていますか?

4

3 に答える 3

6

(:) :: a -> [a] -> [a]
最初の行collatz n = (collatz' n) : 1は強制的1に になり[a]ます。
私はあなたが何かを望んでいた(collatz' n) ++ [1]
if (even n) then (div n 2) else ((3*2)+1)思い((3*n)+1ますcollatz''' 7 = 7

于 2010-07-02T06:45:42.340 に答える
5

唯一の答えは正しいですが、あなたはHaskellを初めて使用するので、おそらくこれはより明確な説明です. :演算子はリストの前に値を追加するため、値をリストに追加しようとしているため無効somelist : 7です。の型が数値のリストであるため、コンパイルされないのはそのためです。(collatz' n) : 1(collatz' n)

を に置き換えてみて: 1ください++ [1]

于 2010-07-02T06:51:39.957 に答える
0

問題に対処する別の方法は、リストの代わりに Data.Sequence 構造を使用することです。シーケンスを使用すると、値を "snoc" (シーケンスの後ろに値を置く) だけでなく、より一般的な "cons" (シーケンスの前に置く) もできます。

span別の解決策は、独自の「takeUntil」関数を作成するために使用することです。

説明させてください:と同じ方法で、使用する関数とリストの場合とspan p xs同じ答えが得(takeWhile p xs, dropWhile p xs)られます。pxssplitAt n xs(take n xs, drop n xs)

とにかく、span独自の「takeUntil」関数を作成するために使用できます。

takeUntil p xs = taken ++ take 1 dropped where
                 (taken, dropped) = span p xs

これは、フォームを使用したときに探していたcollatz n = (collatz' n) : 1フォームです。

これが役立つことを願っています。

于 2010-07-02T18:17:23.443 に答える