遍历多态有限二叉树

时间:2017-05-26 11:18:10

标签: haskell functional-programming binary-tree

我的树有以下数据类型。

data Tree a = Leaf a | Node (Tree a) a (Tree a) deriving ( Show )

我想使用从左到右的深度优先遍历来打印给定树的表示。

目前,我决定采用模式匹配。

showt :: Tree a -> [Char]
showt ( Leaf a ) = [a]
...

当我尝试使用GHCi运行它时,这是我得到的错误

• Couldn't match expected type ‘Char’ with actual type ‘a’
      ‘a’ is a rigid type variable bound by
        the type signature for:
          showt :: forall a. Tree a -> [Char]
        at 2016.hs:31:10
    • In the expression: a
      In the expression: [a]
      In an equation for ‘showt’: showt (Leaf a) = [a]
    • Relevant bindings include
        a :: a (bound at 2016.hs:32:14)
        showt :: Tree a -> [Char] (bound at 2016.hs:32:1)

我不知道问题的来源。 Haskell应该推断出类型,没有?

1 个答案:

答案 0 :(得分:3)

好吧因为data Tree a = ... deriving Show,这意味着aChar

这只意味着Haskell已经自动添加了一个类型实例:

instance Show a => Show (Tree a) where
    -- ...

正如您所看到的,它添加了类型约束:a必须是Show的实例,以便Tree a成为Show的实例。所以我们的第一个结论是 a仍然可以是任何类型

此外,即使aShow的实例,也意味着它是String(或Char) 。它只表示有一些功能可用,如show :: (Show a) => a -> String

所以这里有一些选择:

  • 添加类型约束,并使用show

    showt :: Show a => Tree a -> [Char]
    showt ( Leaf a ) = show a
    --- ...
  • 您将自己限制为String类型的树(或类型Char):

    showt :: Tree Char -> [Char]
    showt ( Leaf a ) = [a]
    --- ...

最后Haskell 可以推断出函数的类型,但是在这里你提供了一个显式类型的签名。但是,如果您省略了签名,则让Haskell自动导出它:

Prelude> let showt ( Leaf a ) = [a]
Prelude> :t showt
showt :: Tree t -> [t]