use*_*154 8 haskell functional-programming functor data-structures
我正在为一个hw问题编写一些代码,它要求我们将树的定义作为functor和foldable的一个实例.当我写下面的代码时:
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]
Run Code Online (Sandbox Code Playgroud)
出现以下错误:
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.
Run Code Online (Sandbox Code Playgroud)
我哪里错了?
谢谢!
[[更新]]
我根据下面答案中的建议对代码进行了更改.这是带错误的代码的链接.如果有人看看它并告诉我哪里错了,那就太好了.
再次感谢!
你不能写这个:
fmap f (Node [Tree a]) = ...
Run Code Online (Sandbox Code Playgroud)
因为Tree
数据类型不是数据构造函数.在模式匹配,你只能使用数据的构造,这将是Leaf
或者Node
在这种情况下.在这里,您甚至不需要匹配子树的每个构造函数,因为您无论如何都要直接传递整个列表:
fmap f (Node t) = fmap f t
Run Code Online (Sandbox Code Playgroud)
但实际上还存在另一个错误.结果fmap
仍然需要是,Tree
所以你需要将结果放回到Node
:
fmap f (Node t) = Node (fmap f t)
Run Code Online (Sandbox Code Playgroud)
就像你已经在处理Leaf
案件一样.
您可以将其fmap
视为修改结构内部值的内容,但根本不会更改结构的形状.即.在列表上进行映射将生成相同长度的列表,并且在树上的映射应该生成相同的树,具有所有相同的分支,但在叶节点中具有不同的值.
您可以将a fold
视为完全删除结构的内容,然后找到将叶节点中的所有值组合为单个值的方法.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
Run Code Online (Sandbox Code Playgroud)
结果foldMap
不应该是Tree
!它只是值,使用映射函数进行转换并使用它们的Monoid
实例进行组合.