我要定义函数:
treeMap :: (a -> b) -> BinaryTree a -> BinaryTree b
采用一个函数和一个二叉树,并生成一个二叉树,其中所有节点都是在给定树上应用该函数的结果
二叉树是:
data BinaryTree a = Nil | BNode a (BinaryTree a) (BinaryTree a)
,我的代码不符合要求。我收到以下错误:
error: Not in scope: data constructor ‘BinaryTree’
treeMap f (BNode x (BinaryTree l) (BinaryTree r)) = | ^^^^^^^^^^
我的代码:
data BinaryTree a = Nil | BNode a (BinaryTree a) (BinaryTree a)
treeMap :: (a -> b) -> BinaryTree a -> BinaryTree b
treeMap f Nil = Nil
treeMap f (BNode x (BinaryTree l) (BinaryTree r)) =
BNode (f x) (BinaryTree (treeMap f l)) (BinaryTree (treeMap f r))
答案 0 :(得分:9)
您的模式(BNode x (BinaryTree l) (BinaryTree r))
不是有效的模式。确实,二叉树的数据定义表明:
data BinaryTree a = Nil | BNode a (BinaryTree a) (BinaryTree a)
所以这意味着BNode
是一个包含三个参数的数据构造函数。最后两个参数的 type 为BinaryTree a
,但是您不能在模式匹配中使用类型。
因此,您应该使用l
和r
作为这些参数的变量(或者您可以使用BinaryTree a
类型的数据构造函数)。
构造BinaryTree a
类型时也是如此。您使用具有BNode x l r
,x
和l
的值的r
调用构造函数,而不必在表达式中指定类型。您可以指定类型,然后使用::
运算符。
因此,您可以使用以下方式修复代码:
treeMap :: (a -> b) -> BinaryTree a -> BinaryTree b
treeMap f Nil = Nil
treeMap f (BNode x l r) = BNode (f x) (treeMap f l) (treeMap f r)
或更优雅:
treeMap :: (a -> b) -> BinaryTree a -> BinaryTree b
treeMap f = go
where go Nil = Nil
go (BNode x l r) = BNode (f x) (go l) (go r)
话虽如此,您可以使用ghc
编译指示让DeriveFunctor
为您派生Functor
实例:
{-# LANGUAGE DeriveFunctor #-}
data BinaryTree a = Nil | BNode a (BinaryTree a) (BinaryTree a) deriving Functor
treeMap
就是fmap :: Functor f => (a -> b) -> f a -> f b
,这里有f ~ BinaryTree
。