2
votes

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 []
2
If we have answered your question to your satisfaction, please accept one of the answers (click the checkmark to the left of the answer you wish to accept). If there is still a point you are unclear on, please explicitly state what you don't understand and explicitly ask for help with it. - dave4420

2 Answers

6
votes

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)
4
votes

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 as) 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.