Странность объединения в экземпляре класса типов
Допустим, у меня есть следующий (глупый) класс:
class BlindMap m where
mapB :: m a -> m b
Я мог бы предоставить следующее []
пример:
instance BlindMap [] where
mapB = map id
Тип RHS является [a] -> [a]
который должен объединиться с [a] -> [b]
, но GHC так не считает:
Couldn't match type ‘a’ with ‘b’
‘a’ is a rigid type variable bound by
the type signature for mapB :: [a] -> [b] at dingas.hs:11:5
‘b’ is a rigid type variable bound by
the type signature for mapB :: [a] -> [b] at dingas.hs:11:5
Expected type: a -> b
Actual type: b -> b
Relevant bindings include
mapB :: [a] -> [b]
In the first argument of ‘map’, namely ‘id’
In the expression: map id
Что мне здесь не хватает?
Заранее спасибо.
2 ответа
Что мне здесь не хватает?
map id
создает список значений некоторого произвольного типа с учетом списка таких значений. [a] -> [b]
обещает создать список значений некоторого произвольного типа с учетом списка значений потенциально другого типа.
Следовательно, он ожидает a -> b
, но ваша функция на основе идентификатора может принимать только то, что она возвращает, так b -> b
,
В общем, вы сказали, что предоставите функции с типом:
forall a b.[a] -> [b]
в ваших определениях экземпляра. Компилятор взял ваше слово на это.
Теперь, когда вы создали экземпляр, компилятору действительно нужно увидеть эту чудесную функцию. И он отклоняет весь код, который делает меньше, чем вы обещали.
Прежде чем продолжить, вы должны попытаться написать функцию
forall a b. a -> b
и вы увидите, что в лучшем случае можете придумать что-то вроде:
f x = f x
g x = error "not terminating."
И до тех пор, пока не будет полезной функции сопоставления элементов, могут быть записаны только следующие экземпляры:
instance BlindMap (Maybe a) where mapB _ = Nothing
instance BlindMap ([a]) where mapB _ = []
и так далее в том же духе.