Ответ 1
fst
имеет тип fst :: (a, b) -> a
, так что это означает, что можно определить функцию:
fst' :: (a, a) -> a
fst' = fst
Ваша функция fst'
является более строгой, чем функция fst
. Независимо от того, что вы заменяете a
в вашей функции fst'
, которая подходит для fst
. Например, если выполняется a ~ Bool
, вы вызываете fst
с подписью fst :: (Bool, Bool) -> Bool
. Но поскольку fst
может работать со всеми a
и b
, хорошо, что оба элемента кортежа являются Bool
, поэтому данный fst
может обрабатывать кортежи для всех возможных типов как для первого, так и для второго элемент из 2-х кортежей, это совершенно нормально, если два элемента имеют одинаковый тип.
Последнее не в порядке, здесь вы определяете:
elem' :: (Eq a, Eq b) => a -> [b] -> Bool
elem' = elem
но elem
имеет тип elem :: Eq a => a -> [a] -> Bool
. Сигнатуры, которые вы можете сделать с помощью функции elem'
, не являются подмножеством сигнатур функции elem
, поскольку вы можете установить a ~ Int
и b ~ Bool
. В этом случае вы ожидаете elem :: Int -> [Bool] -> Bool
, но, очевидно, это не выполняется, поскольку типы Int
и Bool
являются двумя разными типами, а в сигнатуре elem
они оба являются a
.