I have a datatype defined as
data Foo a = Foo a (a -> a)
The Foo data constructor has two parameter value and function. I need to write Monad and Monad transform instance for this.
I am trying to implement functor instance,
instance Functor Foo where
fmap f (Foo x g) = Foo (f x) (g .(f x))
but I got an error Couldn't match type ‘a’ with ‘b’.
This is correct because g only accepts of type a and f x will convert a->b .So next I rewrote as
instance Functor Foo where
fmap f (Foo x g) = Foo (f x) g
I got the same error "Couldn't match type ‘a’ with ‘b’".
I also tried this
instance Functor Foo where
fmap f (Foo x g) = Foo (f x) (f. g x)
I got Occurs check: cannot construct the infinite type: a ~ b -> a for (g.x)
I am stuck, I know function g only accepts of type a and returns type a. but fmap will convert type a to type b. I think I have to apply fmap over g as well, which I am not able to do.
How do I write the instance for the above datatype?
Let us take the types into account, we basically need to convert a Foo a to a Foo b, that means we need to find, given a function a -> b, an element of type a and a function with type a -> a, an element of type b and a function of type b -> b.
Especially the last is difficult, since we are only given a function with type a -> b, and not a function with type b -> a, we can not first convert the input to a a, then process it through the orignal function and then map it back to a b.
It is not entirely impossible to make a mapping that satisfies the types, for example:
fmap1 f (Foo x g) = Foo (f x) (const (f x))
or:
fmap2 f (Foo x g) = Foo (f x) id
But the problem with fmap1 and fmap2 need to satisfy the law:
fmap id = id
In other words fmap id (Foo x g) needs to be equal to Foo x g, now if we use id or const (f x), then id and f x are not always equal to g, at least not if g is a function that can take any form.
If you of course consider Foo x g and Foo x (id x) for example to be equivalent, which might be reasonable in some cases as @leftaroundabout says, then you can implement this as a functor instance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With