实现mapTree函数

时间:2019-05-09 18:04:58

标签: dictionary haskell binary-tree

我要定义函数:

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))

1 个答案:

答案 0 :(得分:9)

您的模式(BNode x (BinaryTree l) (BinaryTree r)) 不是有效的模式。确实,二叉树的数据定义表明:

data BinaryTree a = Nil | BNode a (BinaryTree a) (BinaryTree a)

所以这意味着BNode是一个包含三个参数的数据构造函数。最后两个参数的 type BinaryTree a,但是您不能在模式匹配中使用类型。

因此,您应该使用lr作为这些参数的变量(或者您可以使用BinaryTree a类型的数据构造函数)。

构造BinaryTree a类型时也是如此。您使用具有BNode x l rxl的值的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