Вы уже используете рекурсию. В самом деле, вы используете roseMap f
в терминах самого себя:
roseMap :: (a -> b) -> RoseTree a -> RoseTree b
<b>roseMap f</b> rtree = case rtree of
RoseNode a [] -> allCaps a
RoseNode a sub -> Rose (allCaps a) (map (<b>roseMap f</b> sub))
Но вышеописанное не будет работать по нескольким причинам:
- вы не используете здесь
f
,На самом деле вы пишете Rose (allCaps a)
, поэтому вы не используете f
для сопоставления элементов; sub
должен не передаваться в скобках roseMap f
; - Вы должны использовать
RoseNode
вместо Rose
;и - в вашем первом случае вы возвращаете
allCaps a
вместо RoseNode (allCaps a) []
.
Делать различие между узлом без дочерних элементов или с дочерними элементами не всегда необходимо,Мы можем определить отображение как:
roseMap :: (a -> b) -> RoseTree a -> RoseTree b
roseMap f (RoseNode a xs) = RoseNode (f a) (map (roseMap f) xs)
Так что здесь мы используем f a
вместо этого, и мы выполняем сопоставление для дочерних элементов.
Если мы затем выполняем roseMap
с allCaps
как функция, мы получаем:
Prelude Data.Char> roseMap allCaps things
RoseNode "THING" [RoseNode "ANIMAL" [RoseNode "CAT" [],RoseNode "DOG" []],RoseNode "METAL" [RoseNode "ALLOY" [RoseNode "STEEL" [],RoseNode "BRONZE" []],RoseNode "ELEMENT" [RoseNode "GOLD" [],RoseNode "TIN" [],RoseNode "IRON" []]],RoseNode "FRUIT" [RoseNode "APPLE" [RoseNode "GRANNY SMITH" [],RoseNode "PINK LADY" []],RoseNode "BANANA" [],RoseNode "ORANGE" []],RoseNode "ASTRONOMICAL OBJECT" [RoseNode "PLANET" [RoseNode "EARTH" [],RoseNode "MARS" []],RoseNode "STAR" [RoseNode "THE SUN" [],RoseNode "SIRIUS" []],RoseNode "GALAXY" [RoseNode "MILKY WAY" []]]]
Нам не нужно реализовывать отображение самостоятельно, мы можем включить расширение DeriveFunctor
[ghc-doc] , и пусть Haskell сделает всю работу за нас:
{-# LANGUAGE <b>DeriveFunctor</b> #-}
data RoseTree a = RoseNode a [RoseTree a] deriving (<b>Functor</b>, Show)
мы можем назвать это с помощью fmap :: Functor f => (a -> b) -> f a -> f b
:
Prelude Data.Char> fmap (map toUpper) things
RoseNode "THING" [RoseNode "ANIMAL" [RoseNode "CAT" [],RoseNode "DOG" []],RoseNode "METAL" [RoseNode "ALLOY" [RoseNode "STEEL" [],RoseNode "BRONZE" []],RoseNode "ELEMENT" [RoseNode "GOLD" [],RoseNode "TIN" [],RoseNode "IRON" []]],RoseNode "FRUIT" [RoseNode "APPLE" [RoseNode "GRANNY SMITH" [],RoseNode "PINK LADY" []],RoseNode "BANANA" [],RoseNode "ORANGE" []],RoseNode "ASTRONOMICAL OBJECT" [RoseNode "PLANET" [RoseNode "EARTH" [],RoseNode "MARS" []],RoseNode "STAR" [RoseNode "THE SUN" [],RoseNode "SIRIUS" []],RoseNode "GALAXY" [RoseNode "MILKY WAY" []]]]