用户定义类型的Haskell Show实例-构造函数不在范围内

用户定义类型的Haskell Show实例-构造函数不在范围内,haskell,types,Haskell,Types,对于Haskell来说,这是一个相当新的概念,我尝试着去理解用户定义的类,在阅读了learnyouahaskell之后,我成功地为二叉树定义了以下类: data BTree a = EmptyTree | Node (BTree a) a (BTree a) deriving (Ord, Eq, Show) {- compares value of new node x to root if same, don't insert (no duplicates); if smaller, ins

对于Haskell来说,这是一个相当新的概念,我尝试着去理解用户定义的类,在阅读了learnyouahaskell之后,我成功地为二叉树定义了以下类:

data BTree a = EmptyTree | Node (BTree a) a (BTree a) deriving (Ord, Eq, Show)

{- compares value of new node x to root
if same, don't insert (no duplicates); if smaller, insert into left subtree lSub; if larger, insert into right subtree rSub -}
treeInsert :: (Ord a) => a -> BTree a -> BTree a
treeInsert x EmptyTree = Node EmptyTree x EmptyTree
treeInsert x (Node lSub root rSub)
    | x == root = Node lSub x rSub
    | x < root = Node (treeInsert x lSub) root rSub
    | x > root = Node lSub root (treeInsert x rSub)

--recurses over list of nodes to add
treeFromList :: (Ord a) => [a] -> BTree a -> BTree a
treeFromList [] tree = tree
treeFromList (node:nodes) tree = treeFromList nodes (treeInsert node tree)
我得到一个错误,说“没有(Show(BTree Integer->BTree Integer))的实例” 因使用“print”而产生的

因此,我尝试定义show的一些实例(在一个类似示例中使用堆栈溢出帖子)

但是代码没有编译,我对BTree、Node或EmptyTree的所有引用都会出现错误“不在范围内:数据构造函数”

我不明白为什么它们不在范围内,所以我想知道我对实例的定义是否有误。提前感谢您的帮助

您将类型构造函数(
BTree
)与数据构造函数(
EmptyTree
节点
)混淆了。如果您定义了
instance…
,那么您处于类型级别,因此
instance Show EmptyTree
没有任何意义。您只能使用
b树a
(并且您可能希望将类型约束添加到
a
)来定义它

此外,在您定义的
show…=…
中,您使用的是值,因此
show(节点(BTree a)b(BTree c))=…
也没有任何意义

因此,您可以将
Show
的实例定义为:

instance Show a => Show (BTree a) where
    show EmptyTree = ""
    show (Node a b c) = show a ++ " " ++ show b ++ " " ++ show c

没有因使用“print”而产生的(Show(BTree Integer->BTree Integer))实例

这是因为
treeFromList
接受两个参数

treeFromList [1,2,3]
您可能希望重新排列
treeFromList
,以便它只接受一个参数,并且最初假定为空树。例如:

λ> treeFromList [1,2,3] EmptyTree
Node EmptyTree 1 (Node EmptyTree 2 (Node EmptyTree 3 EmptyTree))
或者使用折叠

treeFromList :: (Ord a) => [a] -> BTree a
treeFromList [] = EmptyTree
treeFromList (node:nodes) = treeInsert node (treeFromList nodes)

返回到显示的第一个错误-问题似乎是因为您将
treeFromList
定义为接受两个输入,一个列表和一个树,而只使用第一个list参数调用它。那么您希望这个函数如何运行呢?对我来说,这个名字意味着它应该获取一个列表并输出一棵树,而您对它的调用方式表明您希望它以这种方式工作。但在这种情况下,你的定义是错误的。(在我看来,您所拥有的应该是函数内部的一个helper函数,主函数应该使用
EmptyTree
作为第二个参数调用它。)如果您感兴趣,
treeFromList
是“just”
execState。遍历(modify.treeInsert)
treeFromList=flip(foldl'(flip treeInsert))
treeFromList [1,2,3]
λ> treeFromList [1,2,3] EmptyTree
Node EmptyTree 1 (Node EmptyTree 2 (Node EmptyTree 3 EmptyTree))
treeFromList :: (Ord a) => [a] -> BTree a
treeFromList [] = EmptyTree
treeFromList (node:nodes) = treeInsert node (treeFromList nodes)
treeFromList :: (Ord a) => [a] -> BTree a
treeFromList = foldr treeInsert EmptyTree