Haskell 如何将函数应用于树的所有元素?
它接受一个函数,并将其应用于rosetree的每个元素。通过将函数Haskell 如何将函数应用于树的所有元素?,haskell,recursion,tree,map-function,Haskell,Recursion,Tree,Map Function,它接受一个函数,并将其应用于rosetree的每个元素。通过将函数allCaps映射到rosetreethings来测试结果。所有元素现在都应该用大写字母书写 我不知道如何使用递归来编写此函数。您已经在使用递归了。事实上,您使用的roseMap f本身就是: data RoseTree a = RoseNode a [RoseTree a] deriving Show things :: RoseTree String things = RoseNode "thing" [
allCaps
映射到rosetreethings
来测试结果。所有元素现在都应该用大写字母书写
我不知道如何使用递归来编写此函数。您已经在使用递归了。事实上,您使用的roseMap f本身就是:
data RoseTree a = RoseNode a [RoseTree a] deriving Show
things :: RoseTree String
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" []
]
],
]
-- Turns string into all upper case
allCaps :: String -> String
allCaps x = map toUpper x
-- This function uses allCaps as a helper function
-- to turn the elements in tree into upper case
roseMap :: (a -> b) -> RoseTree a -> RoseTree b
roseMap f rtree = case rtree of
RoseNode a [] -> allCaps a
RoseNode a sub -> Rose (allCaps a) (map (roseMap f sub)
因此,这里我们使用fa
,并在子对象上执行映射
如果我们随后使用allCaps
函数执行roseMap
,我们得到:
roseMap :: (a -> b) -> RoseTree a -> RoseTree b
roseMap f (RoseNode a xs) = RoseNode (f a) (map (roseMap f) xs)
我们不需要自己实现映射,我们可以启用,让Haskell为我们完成工作:
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" []]]]
提示:玫瑰树顶部的值会发生什么变化,每个子树会发生什么变化?它应该首先更改玫瑰树顶部的元素,然后对其余元素应用相同的函数,但我不知道如何将其转换为函数。谢谢您的回答。我还有一个问题。haskell的递归很难想象,我的意思是我无法想象递归的实现过程。因此,编写正确的递归表达式是很困难的。为了更好地理解递归,我可以在纸上或类似的东西上扩展函数的执行吗?Haskell中的递归与其他语言中的递归没有什么不同。这在Haskell(以及一般的函数式语言)中更为常见,因为这通常是在命令式语言中实现循环的唯一方法,而且在Haskell中比在命令式语言中效率更高。(我无法详细解释原因,但懒惰是其中很大一部分。)至于递归在这种特定情况下的工作原理:玫瑰树由一个
a
类型的标签和一系列其他(子)树组成。将rosemapf
应用于这样一棵树,只需将a
替换为fa
,将每个子树sub
替换为rosemapfsub
。当子树列表为空时,递归最终结束(至少在实践中,理论上不必如此)。如果您尝试使用示例树或更简单的示例树来解决这个问题,我相信您很快就会理解它的工作原理。
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" []]]]
{-# LANGUAGE DeriveFunctor #-}
data RoseTree a = RoseNode a [RoseTree a] deriving (Functor, Show)
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" []]]]