18

Haskell 2010言語レポートは、セクション20.10.1.1で次のように述べています。

deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a]

実際、GHCライブラリに実装すると

deleteBy :: (b -> a -> Bool) -> b -> [a] -> [a]

ただし、実際には、タイプを注釈付きの前者に制限します。

したがって、たとえば、次のように言うことはできません。

foo = deleteBy fsteq 42 [(43, "foo"), (44, "bar"), (42, "baz")] where
    fsteq a (b,_) = a == b

Intと同じではないため(Int, String)

これには何か正当な理由がありますか?

私が尋ねている理由は、正当な理由がない場合は、現在行っているData.ListのFregedeleteByポートに、より一般的なタイプを含めるためです。しかし、多分私は何かを見落としていますか?

編集:@hammarが指摘したように、これは他のxxxBy関数にも当てはまります

4

3 に答える 3

11

タイプを一般化するdeleteByと、非常に実用的な方法で標準に違反します。完全に有効なHaskellプログラムは、未解決のオーバーロードのおかげで無効になります。

これがデモンストレーションです:

class (Num a) => Magic a where
  magic :: a -> Bool

sameMagic :: (Magic a, Magic b) => a -> b -> Bool
sameMagic a b = magic a == magic b

test :: (Magic a) => [a]
test = deleteBy sameMagic 42 [1234]

Haskellでは、このプログラムは完全によくタイプされています。deleteByの制限付きタイプは、42がと同じタイプであることが保証されていることを保証します1234。一般化deleteByされた場合、これは当てはまらないため、タイプ42があいまいになり、プログラムが無効になります。(あまり工夫されていない例が必要な場合は、2つのIntegral値をと比較する関数を検討してtoIntegerください。)

したがって、この制限されたタイプの正当な理由はおそらくありませんが(deleteBy一般化する場合は、提案よりもハンマーのバージョンをお勧めします)、一般化すると標準に違反し、有効なプログラムが破損する可能性があります

于 2012-01-26T01:46:34.373 に答える
10

他の機能との対称性のためだと思いxxxByます。ただし、タイプは依然として不必要に特定されています。私はこれを好むでしょう。

deleteBy :: (a -> Bool) -> [a] -> [a]

次に、部分適用を使用して例を記述できます。

foo = deleteBy (fsteq 42) [(43, "foo"), (44, "bar"), (42, "baz")] where
    fsteq a (b,_) = a == b
于 2012-01-25T15:17:59.780 に答える
7

インゴ、

元の質問では、 HaskellReportがこのようにdeleteByを指定している理由を尋ねているようです。したがって、強い理由がない場合は、フレーゲで別の定義を使用できます(Haskell Reportの適合性を気にしないことを意味します)。

Hammarが言うように、それは他のxxxBy関数のようです:delete(==)を使用し、 deleteByは(==)のような述語を取ります:タイプ(a-> a-> Bool)であり、同値関係であると想定されます。型システムは述語が本当に等価関係であるかどうかをチェックできませんが、それは関数コントラクトです。したがって、xxx​​の意味を知っていれば、xxxByの意味を非常に簡単に理解できます。また、deleteByの場合はそうではないかもしれませんが、場合によっては、述語が指定されたプロパティ(同値関係や全順序など)を持っているという仮定の下で実装が最適化されることがあります。

しかし、Hammarの回答に対するコメントでは、より一般的な実装がレポートに違反するかどうかを尋ねます。さて、タイプが異なる場合、それは文字通り違反ですよね?レポートに従ってコンパイルされるべきではないプログラムは、コンパイラによって受け入れられるためです。したがって、移植性の問題が発生します。コードがより一般的なバージョンを使用している場合、仕様に準拠する別の実装でコンパイルされない可能性があります。その上、それは同値関係の要件を取り除きます。

したがって、より一般的な関数が必要な場合は、単に別の名前で別の関数を定義してみませんか?たとえば、deleteIf

(ハマーの答えについてコメントしたかったのですが、コメントできませんので、ここに書きました。)

于 2012-01-26T00:47:11.720 に答える