Reputation: 119
I got a data type "Cake"
*data Cake = EmptyBox | Food { name :: String
, flavors :: [Cake]} deriving( Read, Eq)*
instance Show Cake where
show cake = prints cake where
prints (Food name []) = name ++ "\n"
I want to print cakes like this (each cake got different flavors)
Cake1
Chocolate
Nutella
Strawberry
Cake2
Chocolate
Vanilla
Cake3
But I got error, doesn't works! How can I do it?
Upvotes: 0
Views: 1117
Reputation: 54233
For test data, I used:
cake1 = Food{name="Cake1"
,flavors=[Food{name="Chocolate"
,flavors=[]}
,Food{name="Nutella"
,flavors=[Food{name="Strawberry"
,flavors=[]}]}]}
cake2 = Food{name="Cake2"
,flavors=[Food{name="Chocolate"
,flavors=[]}
,Food{name="Vanilla"
,flavors=[]}]}
cake3 = Food{name="Cake3"
,flavors=[]}
and wrote Show Cake
as unlines
composed with a function that has type Cake -> [String]
instance Show Cake where
show = unlines . prints where
prints :: Cake -> [String]
prints EmptyBox = []
prints (Food s []) = [s] -- a Food with no subflavors
prints (Food s fs) = s:concatMap (map (" "++) . prints) fs
That last line handles the general case of a Food
with name s
and flavors fs
by mapping prints
over fs
, then mapping (" "++)
over each sublist in that map, and concat'ing them together.
(" "++) :: String -> String
map (" "++) :: [String] -> [String]
map (" "++) . prints :: Cake -> [String]
map (map (" "++) . prints) :: [Cake] -> [[String]]
concat . map (map (" "++) . prints) :: [Cake] -> [String]
concatMap = concat . map
concatMap (map (" "++) . prints) :: [Cake] -> [String]
Each successive level of flavors adds an extra level of indentation (that's what the (" "++)
is for). We can test it:
TestModule> putStrLn $ concatMap show [cake1, cake2, cake3]
Cake1
Chocolate
Nutella
Strawberry
Cake2
Chocolate
Vanilla
Cake3
Upvotes: 0
Reputation: 153172
Since prints :: Cake -> String
and flavors :: [Cake]
, we know
map prints flavors :: [String]
But this doesn't jive with the context in which it is used, since in
" " ++ expr
the " "
is clearly a String
and we therefore expect expr
to be a String
and not a [String]
.
To fix this, you should write or find a function which converts your [String]
into a String
in some way -- there are many candidate behaviors for this type, so you should decide what behavior you want and then find a way to achieve that behavior.
Upvotes: 2