我的树有以下数据类型。
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应该推断出类型,没有?
答案 0 :(得分:3)
好吧不因为data Tree a = ... deriving Show
,这意味着a
是Char
。
这只意味着Haskell已经自动添加了一个类型实例:
instance Show a => Show (Tree a) where
-- ...
正如您所看到的,它添加了类型约束:a
必须是Show
的实例,以便Tree a
成为Show
的实例。所以我们的第一个结论是 a
仍然可以是任何类型。
此外,即使a
是Show
的实例,不也意味着它是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]