Функтор с неправильным аргументом типа

1 zero_coding [2017-07-04 13:25:00]

Я имею следующий тип данных и применил к экземпляру Functor:

data Company a b c = 
    DeepBlue a c
  | Something b

instance Functor (Company a b) where 
  fmap f (Something b) = Something b
  fmap f (DeepBlue a c) = DeepBlue a (f c)

Он компилируется без каких-либо жалоб.

Затем я немного поиграл (я знаю, что это не сработает), из-за любопытства новичка:

data Company a b c = 
    DeepBlue a c
  | Something b

instance Functor (Company a b) where 
  fmap f (Something b) = Something (f b)
  fmap f (DeepBlue a c) = DeepBlue a (f c) 

Затем компилятор жалуется:

D:\haskell\chapter16\src\ChapterExercises.hs:18:26: error:
    * Couldn't match type 'b1' with 'b'
      'b1' is a rigid type variable bound by
        the type signature for:
          fmap :: forall a1 b1.
                  (a1 -> b1) -> Company a b a1 -> Company a b b1
        at D:\haskell\chapter16\src\ChapterExercises.hs:18:3
      'b' is a rigid type variable bound by
        the instance declaration
        at D:\haskell\chapter16\src\ChapterExercises.hs:17:10
      Expected type: Company a b b1
        Actual type: Company a b1 b1
    * In the expression: Something (f b)
      In an equation for 'fmap': fmap f (Something b) = Something (f b)
      In the instance declaration for 'Functor (Company a b)'
    * Relevant bindings include
        b :: b
          (bound at D:\haskell\chapter16\src\ChapterExercises.hs:18:21)
        f :: a1 -> b1
          (bound at D:\haskell\chapter16\src\ChapterExercises.hs:18:8)
        fmap :: (a1 -> b1) -> Company a b a1 -> Company a b b1
          (bound at D:\haskell\chapter16\src\ChapterExercises.hs:18:3)

D:\haskell\chapter16\src\ChapterExercises.hs:18:39: error:
    * Couldn't match expected type 'a1' with actual type 'b'
      'b' is a rigid type variable bound by
        the instance declaration
        at D:\haskell\chapter16\src\ChapterExercises.hs:17:10
      'a1' is a rigid type variable bound by
        the type signature for:
          fmap :: forall a1 b1.
                  (a1 -> b1) -> Company a b a1 -> Company a b b1
        at D:\haskell\chapter16\src\ChapterExercises.hs:18:3
    * In the first argument of 'f', namely 'b'
      In the first argument of 'Something', namely '(f b)'
      In the expression: Something (f b)
    * Relevant bindings include
        b :: b
          (bound at D:\haskell\chapter16\src\ChapterExercises.hs:18:21)
        f :: a1 -> b1
          (bound at D:\haskell\chapter16\src\ChapterExercises.hs:18:8)
        fmap :: (a1 -> b1) -> Company a b a1 -> Company a b b1
          (bound at D:\haskell\chapter16\src\ChapterExercises.hs:18:3)
Failed, modules loaded: none.

Что говорит компилятор?

haskell


2 ответа


6 Решение Mark Seemann [2017-07-04 13:37:00]

Вы объявили Company как тип с тремя родовыми типами: a, b и c. Когда вы создаете экземпляр instance Functor (Company ab) вы сказали, что для любых a и b должна существовать функция fmap с типом:

(c -> d) -> Company a b c -> Company a b d

Функция f имеет тип c → d, поэтому вы не можете использовать b для ввода для нее, потому что у нее нет правильного типа.


2 Lee [2017-07-04 13:34:00]

Ваше определение fmap имеет тип

fmap :: Company a b c -> (c -> d) -> Company a b d

поэтому функция принимает значение типа c. В

fmap f (Something b) = Something (f b)

вы пытаетесь применить функцию c → d к значению типа b которое вызывает ошибку. Фактические переменные типа в сообщении имеют разные имена: a1 - c а b1 - d