大家好日夜! 我有类型:
data FixItem m a = KeepItem|SkipItem|FixItem (m (a -> a))
fixItem f = FixItem $ pure f
我想编写函数mapFix :: (a -> b) -> FixItem m a -> FixItem m b
。当我尝试:
mapFix f SkipItem = SkipItem -- good
mapFix f KeepItem = fixItem f -- error "rigid type"!!!
mapFix f (FixItem mf) = FixItem $ pure (.) <*> (pure f) <*> mf -- too!
所以,我得到错误:
• Couldn't match type ‘b’ with ‘a’
‘b’ is a rigid type variable bound by
the type signature for:
mapFix :: forall (m :: * -> *) a b.
Applicative m =>
(a -> b) -> FixItem m a -> FixItem m b
at src/test.hs:235:11
‘a’ is a rigid type variable bound by
the type signature for:
mapFix :: forall (m :: * -> *) a b.
Applicative m =>
(a -> b) -> FixItem m a -> FixItem m b
at src/test.hs:235:11
Expected type: b -> b
Actual type: a -> b
• In the first argument of ‘fixItem’, namely ‘f’
In the expression: fixItem f
In an equation for ‘mapFix’: mapFix f KeepItem = fixItem f
• Relevant bindings include
f :: a -> b (bound at src/test.hs:236:8)
mapFix :: (a -> b) -> FixItem m a -> FixItem m b
(bound at src/test.hs:236:1)
如何为这种类型编写mapFix或实现Functor实例(FixItem将a
修复为a
,而不是b
,即修复为a -> a
,而不是{{1 }})?
答案 0 :(得分:4)
您无法为数据类型实施Functor
类型类。这是因为
a -> a
在你的一个构造函数中。当你有功能时,你应该更加小心。但简而言之,您在逆变位置具有类型变量a
,因此您无法在此类型变量上实现Functor
。
虽然您可以为您的数据类型实施Invariant
。由于协变和逆变位置均为a
,因此您的数据类型是不变函子。
可以帮到你: