计算树Haskell中的节点数

时间:2019-02-22 06:30:53

标签: haskell

我是Haskell的新手,对某些语法片(来自C / C ++)仍然有些困惑。

我有这个Tree数据类型(如下)和t2的构造函数

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

 t2 :: Tree Bool Int                                                             
 t2 = Node 17 (Node 2 (Leaf True)                                                
                      (Node 7 (Leaf False)                                       
                              (Leaf False)))                                     
              (Leaf True)

我需要编写一个函数来计算树的节点数

 sizeTree :: Tree a b -> Int

我对为什么sizeTree为函数传递“ a”和“ b”感到困惑。是因为存在“ a”的叶子和“ b”的节点?我知道这需要递归调用,但是我应该从哪里开始?

2 个答案:

答案 0 :(得分:3)

多个注释已经解决了您对类型签名的困惑,但是我将尝试另一种查看方式,其细节比注释所允许的多。

我们可以比较这种类型的签名:

sizeTree :: Tree a b -> Int

与列表中的函数相同,请说length函数:

length :: [a] -> Int 

此函数不“使用a作为参数,而是使用[a],它表示元素类型为a的列表。至关重要的是a可以代表 any 类型-明确地将其写为forall a. [a] -> Int是合法的,这清楚地表明该函数可以在{{1}上运行}列表类型。也就是说,一个any函数可以应用于整数列表,字符列表(即字符串)或成对列表length和列表的Double中-希望您能想到。您可能认为这是理所当然的,您可以调用Integerlength [1,2,3]并使它们都起作用-但是,考虑到Haskell强大的类型系统,它只能工作于多态类型。

length "hello"完全相同。这实际上是一个“类型族”,就像列表一样-它本身不是类型,没有类型Tree的值。但是存在类型TreeTree Int Char的值,您可以想到的任何其他值都使用两个“具体类型”来代表Tree String (Int, Double)a。通过声明一个函数b-显式sizeTree :: Tree a b -> Int-您可以确保该函数可用于无限多种具体类型中的任何一种。

关于编写函数本身,再次类似于列表。列表类型虽然是Haskell内置的,但实际上具有两个构造函数,一个用于空列表,一个用于接收元素和一个现有列表(您可以将自己的等效类型定义为sizeTree :: forall a. forall b. Tree a b -> Int-这意味着您可以进行模式化在这两个构造函数上进行匹配,即可:

data List a = Null | Cons a (List a)

,或者对Haskell的本机列表类型使用内置的“语法糖”:

length Null = 0
length (Cons _ l) = 1 + length l

(如果您对length [] = 0 length (_:l) = 1 + length l 感到困惑,它代表任何适当类型的值,这意味着在这种情况下,我们不在乎它的值,如果可以您会更愿意说_,那将意味着完全一样的事情。)

希望这是足够的背景知识,可以帮助您了解正在发生的事情,并填写@Rusi给您的开头-因为它们是您x类型的两个构造函数,因此您需要在这两个。进一步的提示:Tree a b构造函数将涉及对Node的递归调用,就像sizeTree定义的第二行也使用递归调用一样。

还有其他问题,请随时提问。

答案 1 :(得分:1)

像这样开始

sizetree (Leaf x)  = ???
sizetree (Node y left right) = ???

填写???