Haskell 树作为函子和可折叠的实例

Haskell 树作为函子和可折叠的实例,haskell,data-structures,functional-programming,functor,Haskell,Data Structures,Functional Programming,Functor,我正在为一个硬件问题编写一个小代码,它要求我们将树定义为函子和可折叠的实例。当我写下面的代码时: import Data.Foldable import Data.Monoid data Tree a = Leaf a | Node [Tree a] deriving (Show) instance Functor (Tree) where fmap f (Leaf a) = Leaf (f a) fmap f (Node

我正在为一个硬件问题编写一个小代码,它要求我们将树定义为函子和可折叠的实例。当我写下面的代码时:

 import Data.Foldable
 import Data.Monoid

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

 instance Functor (Tree) where
    fmap f (Leaf a) = Leaf (f a) 
    fmap f (Node [Tree a]) = fmap f [Tree a]

 instance Foldable (Tree) where
    foldMap f (Leaf a) = f a
    foldMap f (Node [Tree a]) = foldMap f `mappend` [Tree a]
出现以下错误:

hw.hs:10:19:
Not in scope: data constructor `Tree'
Perhaps you meant `True' (imported from Prelude)

hw.hs:10:38:
Not in scope: data constructor `Tree'
Perhaps you meant `True' (imported from Prelude)

hw.hs:14:22:
Not in scope: data constructor `Tree'
Perhaps you meant `True' (imported from Prelude)

hw.hs:14:54:
Not in scope: data constructor `Tree'
Perhaps you meant `True' (imported from Prelude)
Failed, modules loaded: none.
我哪里做错了

谢谢

[[更新]]

我已根据以下答案中的建议对代码进行了更改。下面是指向错误代码的链接。如果有人能看一下,告诉我哪里错了,那就太好了


再次感谢

你不能这样写:

fmap f (Node [Tree a]) = ...
因为
是数据类型而不是数据构造函数。在模式匹配中,您只能使用数据构造函数,在这种情况下,数据构造函数将是
Leaf
Node
。在这里,您甚至不需要为子树匹配每个构造函数,因为您正在直接传递整个列表:

fmap f (Node t) = fmap f t
但实际上还有另一个错误。
fmap
的结果仍然需要是一个
,因此您需要将结果放回
节点中

fmap f (Node t) = Node (fmap f t)
就像您已经在处理
Leaf
案例一样


您可以将
fmap
视为修改结构内部值的东西,但根本不改变结构的形状。也就是说,映射到一个列表上会产生一个长度相同的列表,映射到一棵树上会产生一个相同的树,具有所有相同的分支,但叶节点中的值不同

您可以将折叠视为完全删除结构的东西,然后找到一种方法将叶节点中的所有值合并为一个值。
foldMap的类型有助于:

 foldMap :: (Foldable t, Monoid m) => 
         (a -> m) -- mapping function from `a` to the monoid result
      -> t a      -- A tree node containing values of type `a`
      -> m        -- a monoid

foldMap
的结果不应是
!它只是值,通过映射函数进行转换,并使用它们的
Monoid
实例进行组合。

从技术上讲
Tree
是一种构造函数:一种类型构造函数。因此,它生成类型vs
节点values@jozefg有点挑剔!但好吧,我改了:)@PeterHall非常感谢!我已根据您的建议对您的代码进行了更改,但它仍然会抛出错误消息。您可以在此处查看带有错误消息的更新代码:@user2994154当您为
(树a)
定义
fmap
时,
fmap
的第一个参数是接受
(a->b)
的函数。在您的定义
节点(fmap f t)
中,您期望
fmap
是一个
树a->treeeb
。为什么不
Node(fmap(fmap f)t)
这相当于
Node[fmap f a | a@homam我刚刚发现了这一点,但感谢您的反馈。可折叠实例会以类似的方式工作吗?