Не удалось сопоставить тип `a` с` a1` - PullRequest
0 голосов
/ 26 октября 2018

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

{-# 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)) компиляции, в чем разница?

1 Ответ

0 голосов
/ 26 октября 2018

Вопрос 1

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

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

Вопрос 2

Для этого есть веские причины.Одним из них является то, что может быть чрезвычайно полезно (для поддержки программных инвариантов или для управления разрешением экземпляра) задавать параметр типа phantom .Эти методы были бы бесполезны, если бы компилятор их просто игнорировал.(Примечание: вы можете игнорировать их, когда вам это нужно, и 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
...