Не удалось сопоставить тип `a` с` a1`

Я делаю упражнение в главе 16. Программирование на Haskell из первых принципов. Вопрос в том, чтобы попросить нас написать определение функтора для типа данных:

{-# LANGUAGE FlexibleInstances #-}
newtype Flip f a b = Flip (f b a) deriving (Eq, Show)
newtype K a b = K a
instance Functor (Flip K a) where
  fmap = undefined

Вот моя попытка:

{-# LANGUAGE FlexibleInstances #-}
newtype Flip f a b =
  Flip (f b a)
  deriving (Eq, Show)

newtype K a b =
  K a

-- instance Functor (K a) where
-- fmap _ (K a) = K a

instance Functor (Flip K a) where
  fmap _ (Flip (K a)) = Flip (K a)

но он не компилируется:

chapEx2.hs:17:25: error:
    • Couldn't match type ‘a1’ with ‘b’
      ‘a1’ is a rigid type variable bound by
        the type signature for:
          fmap :: forall a1 b. (a1 -> b) -> Flip K a a1 -> Flip K a b
        at chapEx2.hs:17:3-6
      ‘b’ is a rigid type variable bound by
        the type signature for:
          fmap :: forall a1 b. (a1 -> b) -> Flip K a a1 -> Flip K a b
        at chapEx2.hs:17:3-6
      Expected type: Flip K a b
        Actual type: Flip K a a1
    • In the expression: Flip (K a)
      In an equation for ‘fmap’: fmap f (Flip (K a)) = Flip (K a)
      In the instance declaration for ‘Functor (Flip K a)’
    • Relevant bindings include
        a :: a1 (bound at chapEx2.hs:17:19)
        f :: a1 -> b (bound at chapEx2.hs:17:8)
        fmap :: (a1 -> b) -> Flip K a a1 -> Flip K a b
          (bound at chapEx2.hs:17:3)
   |
17 |   fmap f (Flip (K a)) = Flip (K a)
   |                         ^^^^^^^^^^

Может кто-нибудь объяснить сообщение об ошибке? Меня просто смущает сообщение об ошибке:

  1. Почему компилятор делает вывод, что Actual type - это Flip K a a1, а не Flip K a b?
  2. Почему компилятор пытается сопоставить третий параметр K? В определении типа K есть только один a, но нет b, b встречается только в левой части объявления класса данных (левая часть знака =), но не в объявлении класса типа (правая часть знака =) newtype K a b = K a.
  3. Почему Flip (K a) нельзя заменить на Flip x?
  4. Нашел компиляции fmap f (Flip (K a)) = Flip (K (f a)), в чем разница?
0
0
286
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вопрос 1

Вы ошиблись. Flip означает, что вам необходимо отобразить параметр первыйK:

instance Functor (Flip K a) where
  fmap f (Flip (K a)) = Flip (K (f a))

вопрос 2

Для этого есть веские причины. Одна из них заключается в том, что может быть чрезвычайно полезно (для поддержки инвариантов программы или для управления разрешением экземпляра) дать типу параметр фантом. Эти методы были бы бесполезны, если бы компилятор просто игнорировал их. (Примечание: вы можете игнорировать их, когда вам нужно, и Data.Coerce предоставляет для этого несколько расширенных инструментов. Вероятно, вы еще не готовы к принуждениям).

Другая причина заключается в том, что было бы значительно сложнее выяснить, какие типы соответствуют другим типам, так как вам придется детально изучить каждый из них. Наверное, причин больше.

В сторону

FlexibleInstances здесь кажется довольно неудобным и ограничивающим. Вот как бы я это сделал:

-- A functor in the second to last type argument
class Functor2 p where
  fmap2 :: (a -> a') -> p a b -> p a' b

instance Functor2 K where
  fmap2 = -- you fill in the blank

instance Functor2 p => Functor (Flip p b) where
  fmap = -- you fill in the blank

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