Reputation: 5955
I create my own data type, and try to implement functor method as follow:
data Hieu a = Hieu [a] deriving (Show, Read, Eq)
instance Functor Hieu where
fmap f (Hieu [x]) = Hieu (f [x])
It's very simple piece of code but it failed. Can you explain why?
Thanks for all your responses. Now I understand that I apply functor only for one case. I tried to rewrite as follow, without using map
data Hieu a = Hieu [a] deriving (Show, Read, Eq)
consHieu :: a -> (Hieu a) -> (Hieu a)
consHieu x (Hieu xs) = Hieu (x:xs)
instance Functor Hieu where
fmap f (Hieu (x:xs)) = consHieu (f x) (fmap f (Hieu xs))
fmap f (Hieu []) = Hieu []
Thanks for all your responses. Now I understand that I apply functor only for one case. I tried to rewrite as follow, without using map
data Hieu a = Hieu [a] deriving (Show, Read, Eq)
consHieu :: a -> (Hieu a) -> (Hieu a)
consHieu x (Hieu xs) = Hieu (x:xs)
instance Functor Hieu where
fmap f (Hieu (x:xs)) = consHieu (f x) (fmap f (Hieu xs))
fmap f (Hieu []) = Hieu []
Upvotes: 2
Views: 223
Reputation: 8930
You're only handling a single case, a one-element list, and handling it incorrectly. Type-level [a]
(the type of lists of any length of a
s) is very different from value-level [x]
(a list containing exactly one element, called x
)!
The correct instance would involve using the function in a more involved way.
fmap :: (a -> b) -> Hieu a -> Hieu b
fmap f (Hieu xs) = Hieu (`...`)
At the ...
, we have f :: a -> b
and xs :: [a]
, and we want something :: [b]
. There's a natural way to get that -- map the function over the list.
So a correct instance would look like:
instance Functor Hieu where
fmap f (Hieu xs) = Hieu (map f xs)
Any other instance -- for example, one that only handles one-element lists -- wouldn't obey the Functor laws, since we want fmap id h
to always be the same thing as h
.
Upvotes: 4
Reputation: 139930
In the expression f [x]
you're applying f
to a list, but that's not allowed since the type signature of fmap
is (a -> b) -> Hieu a -> Hieu b
. You're not allowed to restrict f
to [a] -> [b]
.
Perhaps you meant to write
instance Functor Hieu where
fmap f (Hieu [x]) = Hieu [f x]
This would compile, but it would only work if the list has exactly one element. The normal way of making Hieu
a functor would be to use map
to apply the function to all of the elements like so:
instance Functor Hieu where
fmap f (Hieu xs) = Hieu (map f xs)
Upvotes: 6