7

haskell に次の zip 関数の実装があります

myzip (a:b) (z:g)
    | b == [] = []
    | g == [] = []
    | otherwise = (a,z) : myzip b g

ghciにロードすると、次のエラーが発生します

No instance for (Eq b)
  arising from a use of `=='
In the expression: g == []
In a stmt of a pattern guard for
               an equation for `myzip':
  g == []
In an equation for `myzip':
    myzip (a : b) (z : g)
      | b == [] = []
      | g == [] = []
      | otherwise = (a, z) : myzip b g

失敗しました。モジュールがロードされました: なし。

なぜこれが機能しないのか、私には本当にわかりません。誰でも私に助けを提供できますか?

4

1 に答える 1

14

実際、質問で指定した関数は正常にコンパイルされます。あなた持っていたものが代わりにあった場合、引用したエラーが発生します:

myzip :: [a] -> [b] -> [(a, b)]
myzip (a:b) (z:g)
    | b == [] = []
    | g == [] = []
    | otherwise = (a, z) : myzip b g

任意のmyzipのリストで機能することを示す明示的な型シグネチャを使用して、. しかし、あなたは と を使用しました。等値演算子どの型にも定義されておらず、型クラスのメンバーである型に対してのみ定義されているため、記述したコードは指定した型と一致しません。abb == []g == []Eq

これは、エラー メッセージが非常に率直に言っていることですが、型クラスを学習したばかりで、まだ型クラスに慣れていない場合は、少し不明確です。

それをmyzip言うために型シグネチャを変更し、型クラスのメンバーである必要がある場合、指定したコードは機能します。abEq

myzip :: (Eq a, Eq b) => [a] -> [b] -> [(a, b)]

または、型シグネチャを完全にオフのままにしておくと (質問で行ったように)、GHC は演算子を使用したという事実から実際にこの型を推測し==、コードはそのままコンパイルされます。

ただし、リストが空かどうかのチェックは==演算子を使用しなくても実行できるmyzipため、実際に任意の型aおよびに対して動作するように記述できますb。1 つの方法は、次のnull関数を使用することです。

myzip :: [a] -> [b] -> [(a, b)]
myzip (a:b) (z:g)
    | null b = []
    | null g = []
    | otherwise = (a, z) : myzip b g

しかし、もっと一般的な方法は単純に複数の式を使って を定義することですmyzip。ベースケースはパターンと一致し[]、メインケースはリストが空でないと仮定します:

myzip :: [a] -> [b] -> [(a, b)]
myzip (a:[]) _ = []
myzip _ (z:[]) = []
myzip (a:b) (z:g) = (a, z) : myzip b g

このスタイルは、実装にバグがあることも明らかにしていることに注意してください。aあなたは最後のorを捨てておりz、リストが完全に空であるというケースはありません!

あなたの方程式が言っmyzip (a:b) (z:g)て、空のリストに対してチェックしたとき、それは実際には遅すぎて間違ったことをチェックしていました。isかどうかを確認する必要はありません。リスト全体が空かどうかを確認する必要があります。しかし、あなたはそれが空ではないとすでに想定しており、それを に分解しました。これにより、コードは (a) 圧縮する必要がある要素の最後のペアを破棄するため、間違った結果を返し、(b) 引数の 1 つが空のリストの場合にエラーを生成します。bgb[]a:b

通常、リストの再帰は次のようになります。

myzip :: [a] -> [b] -> [(a, b)]
myzip [] _ = []
myzip _ [] = []
myzip (a:b) (z:g) = (a, z) : myzip b g

これは正しく動作します。

于 2013-05-05T04:45:05.587 に答える