Странность объединения в экземпляре класса типов

Допустим, у меня есть следующий (глупый) класс:

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 _ = []

и так далее в том же духе.

Другие вопросы по тегам