递归树传递额外的整数

时间:2018-05-14 16:44:53

标签: haskell tree

我需要这个用于我的作业,我已经完成了我的解决方案,但我还有最后一个子问题,我无法弄清楚如何解决..

Clean-Rebuild-Run

所以我试图通过这个功能实现的是: 拿一棵树,将树映射到自己,但将参数mi改为(transformNote mi 2)。

此代码按预期工作并执行所有操作,但我实际需要的是一个函数

type Notes = [(Int,Int,Int,Int)]
data Tree = Leaf Notes | Node Notes [Tree]]
    deriving(Eq,Show)

identity :: Tree -> Tree
identity (Leaf mi   ) = Leaf (transformNote mi 2)
identity (Node mi xs) = Node (transformNote mi 2) (map identity xs)

这样我的功能变成了这样的东西:

identity :: Tree -> Int -> Tree

以来这不起作用
identity :: Tree -> Int -> Tree
identity (Leaf mi   ) amount = Leaf (transformNote mi amount)
identity (Node mi xs) amount = Node (transformNote mi amount) (map identity xs amount)

我尝试了很多方法来解决这个问题,在条款周围抛出金额变量但似乎没有任何效果。我无法理解为什么我的解决方案都不起作用。

有人可以帮忙吗? THX

2 个答案:

答案 0 :(得分:2)

如果你概括一下,这实际上更容易。将Tree参数化,使其成为Functor的实例:

data Tree a = Leaf a | Node a [Tree a] deriving (Eq,Show)

instance Functor Tree where
  fmap f (Leaf x) = Leaf (f x)
  fmap f (Node x xs) = Node (f x) (fmap (fmap f) xs)

现在你可以根据自己的需要转换Tree的元素:

identity :: Tree Notes -> Int -> Tree Notes
identity t amount = fmap (\n -> transformNote n amount) t

顺便说一句,identity是函数的错误名称,因为通过数学(和Haskell)约定,标识函数是

id :: a -> a
id x = x

即,简单地返回其参数的函数。

答案 1 :(得分:1)

所有子树s,需要替换为identity s amount。这意味着我们可以编写 lambda表达式 \s -> identity s amount,从而转换单个子树。然后我们可以在map

中使用该表达式
identity :: Tree -> Int -> Tree
identity (Leaf mi   ) amount = Leaf (transformNote mi amount)
identity (Node mi xs) amount = Node nmi (map (\s -> identity s amount) xs)
    where nmi = transformNote mi amount

where子句仅用于使代码适合可用的页面宽度。

但这很难看。我们可以使用翻转这两个参数的https://developer.mozilla.org/en-US/docs/Web/API/Position。在这种情况下,我们可以将其写成:

identity :: Tree -> Int -> Tree
identity (Leaf mi   ) amount = Leaf (transformNote mi amount)
identity (Node mi xs) amount = Node nmi (map (flip identity amount) xs)
    where nmi = transformNote mi amount

因为它经常引入丑陋的表达,这就是为什么在Haskell中通常会翻转参数本身的原因之一:

-- flipped version
identity2 :: Int -> Tree -> Tree
identity2 amount (Leaf mi   ) = Leaf (transformNote mi amount)
identity2 amount (Node mi xs) = Node nmi (map (identity2 amount) xs)
    where nmi = transformNote mi amount