0

Haskell で、1 つのリストを取り、それを 2 つの均等なサイズのリストに分割する関数に取り組んでいます。ここに私が持っているものがあります:

split (x:y:xs) = split2 ([((length(x:y:xs) `div` 2)-2) : x ++ y] : [xs])
split2 (x:xs:[y:ys]) = split2 ((x-1) : [xs] ++ y : [ys])
split2 (0:xs:[y:ys]) = (xs:[y:ys])

この関数は、リストの最初の 2 つの要素を取り、それらをリスト #2 にまとめ、最初のリストを 2 番目の要素として追加します。次に、リストの長さを取得し、それを 2 で割って、最初のリストから 2 つの要素が既に削除されていることを考慮して、何回実行する必要があるかを調べます。次に、これら 2 つの情報を取得し、それを split2 に入れます。これは、最初のリストから別の要素を取得し、最初の要素の 2 番目のリストに追加します。また、実行回数から 1 をカウントダウンしてから、再度実行します。

問題は、実行すると次のようになることです。

Functions.hs:19:49:
    Occurs check: cannot construct the infinite type: t0 = [t0]
    In the first argument of `(:)', namely `(y)'

19 は、最初の split2 関数である 2 行目を示しています。このエラーを修正する方法が正確にはわかりません。何か案は?

4

4 に答える 4

0

いくつかの提案

  • すべての関数に型を書き込みます。コードが読みやすくなり、エラーの検出にも役立ちます。

  • のタイプは++[a] -> [a] -> [a]要素とともにリストの長さを追加しています。list は均一な型でなければならず、 length はInttype を返すため、コンパイラはsplitasの型を推測 [[Int]] -> tします (split2 が type を返すと仮定しますt)。

  • ([((length(x:y:xs)div2)-2) : x ++ y] : [xs])をsplit2 に渡すとき 。xsis of type は typeで[[Int]]あることを意味する ため、コンパイラはtoの型を推測します。[xs][[[Int]]]split2[[[Int]]] -> t

現在、split2 の定義で

 split2 (x:xs:[y:ys]) = split2 ((x-1) : [xs] ++ y : [ys])

ysはタイプ[[Int]]なのでy、タイプ[Int]です。xsはタイプ[[Int]]ですが、あなたはやっています。つまり、との[xs] ++ y両方が同じタイプである必要があります (一部の場合)。[xs]y[a]a

型を提供していないため、コンパイラはそのような型を推測する方法を完全に混乱させています。

単純にリストを 2 つの等しい部分に分割したい場合は、次のようなもっと単純なことをしないでください。

split3 :: [a] -> ([a], [a])
split3 [] = ([],[])
split3 [x] =  ([x],[])
split3 (x:y:xs) = let (xs',ys') = split3 xs in (x:xs',y:ys')
于 2012-10-09T05:09:46.313 に答える
0

Haskell では、リストの要素はすべて同じ型である必要があります。あなたの関数では、リストには、Int、元のリストの要素、および元のリストのサブリストの混合が含まれており、これらはすべておそらく異なる型です。

また、リストと要素を追加する方法についても混乱しています。x ++ y は x と y がそれ自体リストである場合にのみ使用できますが、 x : y は y がリストで x がリストの要素である場合にのみ使用できます。x と y を要素として含む新しいリストを作成するには、代わりに [x, y] を使用します (x:[y] も機能します)。同様に [xs] ++ y は xs ++ [y] である必要があります。

基本的なアルゴリズムを変更せずに、最も簡単な解決策は、おそらく split2 に 3 つの個別の引数をとらせることです。

split (x:y:xs) = split2 ((length(x:y:xs) `div` 2)-2) [x,y] xs
split2 n xs (y:ys) = split2 (n-1) (xs++[y]) ys
split2 0 xs ys = [xs,ys]
于 2012-10-09T05:24:57.760 に答える
0

Haskell のリストは同種の型であると想定されているのに対し、関数に値としてではなくリストで状態を渡しているようです。これは、異種の値のリストを作成しているようにコンパイラに見えるときに問題を引き起こします.

それ以外の

split2 (0:xs:[y:ys])

このように、異なる引数/値を関数に別々に渡す必要があります

split2 n xs (y:ys)

探している機能は、標準ライブラリ関数にも再現されています。

halveList xs = splitAt (length xs `div` 2) xs
于 2012-10-09T05:26:00.350 に答える