用户定义类型构造函数的Show的Haskell实例不在作用域中



对Haskell来说是个新手,我试图理解用户定义的类,经过大量的混乱和阅读,我成功地为二进制树定义了以下类:

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)

上面的代码可以编译,但当我尝试运行以下代码时:

treeFromList [1,2,3]

我收到一个错误,说"没有(Show(BTree Integer->BTree Integr(的实例"因使用"打印"而产生

所以我试图定义一些show的实例(在类似的例子中从堆栈溢出的帖子中工作(

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

但代码没有编译,我对BTree、Node或EmptyTree的所有引用都给出了错误"不在范围内:数据构造函数">

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

treeFromList [1,2,3]

没有因使用"print"而产生的(Show(BTree Integer->BTree Integr((的实例

这是因为treeFromList有两个参数。

λ> treeFromList [1,2,3] EmptyTree
Node EmptyTree 1 (Node EmptyTree 2 (Node EmptyTree 3 EmptyTree))

您可能希望重新排列treeFromList,使其只接受一个参数,并且最初假定为一个空树。例如:

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

您混淆了类型构造函数(BTree(和数据构造器(EmptyTreeNode(。如果您定义了instance …,那么您处于类型级别,所以instance ShowEmptyTree没有意义。您只能用BTree a来定义它(并且您可能希望向a添加类型约束(。

此外,在你对show … = ...的定义中,你正在使用值,所以show (Node(BTree a)b(BTree c)) = …也没有意义。

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

instanceShow a=> Show (BTreea) where
showEmptyTree= ""
show (Nodeabc) = show a ++ " " ++showb ++ " " ++ show c

因此,在这里,我们将EmptyTree映射到空字符串,并且对于具有类型为BTree aac值的Node a b c,我们返回show a ++ " " ++ show b ++ " " + show c

但是,请注意,Show的实现将导致不明确的字符串,因为不同的树可以返回

相同的也就是说,为Show (BTree a)定义一个实例不会解决根本问题。事实上,它抱怨的原因是而不是,因为它不能显示Show a => BTree a,错误说它不能显示一个BTree Integer -> BTree Integer,这是一个函数。

你应该用构建一个树

treeFromList [1,2,3]EmptyTree

最新更新