Функтор с неправильным аргументом типа
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