Reputation: 3749
Good day/night everyone! I have type:
data FixItem m a = KeepItem|SkipItem|FixItem (m (a -> a))
fixItem f = FixItem $ pure f
and I want to write function mapFix :: (a -> b) -> FixItem m a -> FixItem m b
. When I try:
mapFix f SkipItem = SkipItem -- good
mapFix f KeepItem = fixItem f -- error "rigid type"!!!
mapFix f (FixItem mf) = FixItem $ pure (.) <*> (pure f) <*> mf -- too!
So, I get error:
• 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)
How to write mapFix or implement Functor instance for such type (FixItem fixes a
to a
, not to b
, i.e. fix is a -> a
, not a -> b
)?
Upvotes: 1
Views: 82
Reputation: 9179
You can't implement Functor
type class for your data type. It's because of
a -> a
inside one of your constructors. When you have functions, you should be more careful. But in short, you have type variable a
in contravariant position so you can't implement Functor
over this type variable.
Though you can implement Invariant
for your data type. Because a
in both covariant and contravariant positions, your data type is invariant functor.
Can help you:
What is a contravariant functor?
Upvotes: 4