私は Haskell 初心者で、関数の型バインディングと Haskell がそれをどのように強制するかを理解しようとしています。たとえば、関数 の型が であってもfst
、fst :: (a, b) -> a
コンパイラは関数 に対してエラーを出力しませんfst'
。しかし、コンパイラは関数 の型バインディングに対してエラーを出力しますelem'
。
fst' :: (a,a) -> a
fst' s = fst s
elem' :: (Eq a, Eq b) => a -> [b] -> Bool
elem' x xs = elem x xs
ベストアンサー1
fst
タイプとして持つfst :: (a, b) -> a
つまり、関数を定義しても問題ありません。
fst' :: (a, a) -> a
fst' = fst
あなたのfst'
機能はより制限的な関数よりも。関数でfst
何を置き換えても、については問題ありません。たとえば が成り立つ場合、シグネチャ でを呼び出します。ただし、はすべての とを処理できるため、タプルの両方の要素が であっても問題ありません。したがって、が 2 タプルの最初と 2 番目の項目の両方に対してすべての可能な型のタプルを処理できることを考えると、2 つの項目が同じ型であっても間違いなく問題ありません。a
fst'
fst
a ~ Bool
fst
fst :: (Bool, Bool) -> Bool
fst
a
b
Bool
fst
後者はないわかりました。ここで定義します:
elem' :: (Eq a, Eq b) => a -> [b] -> Bool
elem' = elem
しかし、elem
タイプがあるelem :: Eq a => a -> [a] -> Bool
関数で作成できるシグネチャは、およびを設定できるため、 関数elem'
のシグネチャのサブセットではありません。その場合 が期待されますが、と型は 2 つの異なる型であり、シグネチャではこれらは両方とも であるため、明らかにこれは成り立ちません。elem
a ~ Int
b ~ Bool
elem :: Int -> [Bool] -> Bool
Int
Bool
elem
a