2013-05-07 60 views
1

我想编写一个treeFold函数,它需要:一个类型为'a - > b - > a的函数f,一个类型为a的值x,名为t的A树b以及返回a类型的值。通过执行树的按顺序遍历来计算返回值,并通过x传递部分结果。 这里是我的代码:运行我的foldTree函数时发生错误

import Control.Exception 
import Control.Monad 
import Control.DeepSeq 
import qualified Data.List as List 
import Test.HUnit 

data Tree a = Empty 
      | Node a (Tree a) (Tree a) 
      deriving (Show, Eq) 



insertTree :: (Ord a, Show a) => Tree a -> a -> Tree a 
insertTree Empty x = Node x Empty Empty 
insertTree (Node v tLeft tRight) x 
    | x == v = Node v tLeft tRight 
    | x < v = Node v (insertTree tLeft x) tRight 
    | x > v = Node v tLeft (insertTree tRight x) 


createTree :: (Ord a, Show a) => [ a ] -> Tree a 
createTree = foldl insertTree Empty 

intTree = createTree [9,7,2,8,6,0,5,3,1]

listTree = createTree (List.permutations [ 0 .. 3 ]) 

strTree = createTree [ "hello" 
        , "world" 
        , "lorem" 
        , "ipsum" 
        , "dolor" 
        , "sit" 
        , "amet" 
        ] 
treeFold :: (a -> b -> b -> b) -> b -> Tree a -> b 
treeFold f z Empty = z 
treeFold f z (Node v l r) = f v (subfold l) (subfold r) 
    where subfold = foldTree f z 

但是当我运行的代码,我得到了“无法匹配类型错误”。我想知道如何解决这个问题?例如:Main> treeFold(+)10 intTree,而不是得到Main> 51,我得不到类型错误。任何帮助是极大的赞赏。

+0

看看'treeFold'期望的第一个参数的类型:'a - > b - > b - > b'。现在看'(+)'的类型:(数字a)=> a - > a - > a'。他们不匹配。您需要提供三个参数的函数,但“(+)”只接受两个参数。 – 2013-05-07 00:50:43

+0

这里是固定的tree折叠代码:treeFold ::(a→b→a)→a→树b→a treeFold fz Empty = z treeFold fz(Node lxr)= \t treeFold f(fx (treeFold fzr))l ...但是直到得到sam e错误。 – user2210328 2013-05-07 01:44:49

+0

您的原始'treeFold'代码是正确的。错误在于你提供了'(+)'作为参数。你需要为'treeFold'提供除(+)之外的东西。 – 2013-05-07 02:18:50

回答

1

在你的函数

treeFold :: (a -> b -> b -> b) -> b -> Tree a -> b 
treeFold f z Empty = z 
treeFold f z (Node v l r) = f v (subfold l) (subfold r) 
    where subfold = foldTree f z 

您使用f三个值:v(subfold l)(subfold r)。这就是为什么你的类型签名要求f需要三个参数。

在我看来,你会更好应用两个参数f两次,一次v(subfold l),另结合结合起来,与(subfold r)

treeFold f z Empty = z 
treeFold f z (Node v l r) = f (f v (subfold l)) (subfold r) 
    where subfold = treeFold f z 

这也意味着,如果我们假设f :: a -> b -> c,然后subfold l :: b因为f v (subfold l),而且subfold l :: c,因为它从treeFold返回。因此cb是相同类型(c ~ b)和f v (subfold l) :: b。这被用作第一个f的第一个参数,所以a ~ b也是如此。因此,对于这个新的使用f的两倍版本,

treeFold :: (b -> b -> b) -> b -> Tree b -> b 
相关问题