gpt4 book ai didi

haskell - 如何将函数应用于树的所有元素?

转载 作者:行者123 更新时间:2023-12-02 14:07:26 25 4
gpt4 key购买 nike

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)

它接受一个函数,并将其应用于玫瑰树的每个元素。通过将函数 allCaps 映射到 Rosetree things 来测试结果。所有元素现在都应该以大写形式书写。

我不知道如何使用递归来编写这个函数。

最佳答案

正在使用递归。事实上,您使用的是 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))

但是由于以下几个原因,上述方法不起作用:

  1. 这里没有使用f。事实上,您编写了 Rose (allCaps a),因此您不使用 f 来映射元素;
  2. sub 不应roseMap f 的括号中传递;
  3. 您应该使用RoseNode而不是Rose;和
  4. 在第一种情况下,您返回 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 来代替,并对子项执行映射。

如果我们然后使用 allCaps 作为函数执行 roseMap,我们会得到:

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 extension [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" []]]]

关于haskell - 如何将函数应用于树的所有元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58268054/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com