对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
(和数据构造器(EmptyTree
和Node
(。如果您定义了instance …
,那么您处于类型级别,所以instance Show
没有意义。您只能用EmptyTreeBTree 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 a
的a
和c
值的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