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我刚刚发现了这一点,但感谢您的反馈。可折叠实例会以类似的方式工作吗?