我正在尝试编写一个可以检查给定数字是否出现在树中的小程序。这是我的代码:
import Prelude
data Tree = Node Int [Tree]
Tree happytree = Node 5 [Node 1 [Node 6 []],Node 8 [],Node 2 [Node 1 [],Node 4 []]]
contains1 :: [Tree] -> Int -> Bool
contains1 [] x = False
contains1 (a:as) x = contains a x || contains1 as x
contains :: Tree -> Int -> Bool
contains (Node x []) y = x==y
contains (Node x as) y = x==y || contains1 as y
我收到错误消息
Not in scope: data constructor ‘Tree’
Perhaps you meant ‘True’ (imported from Prelude)
这是什么意思? 我想知道是否有人可以给我一个如何编写我的包含函数的建议,而无需编写帮助函数contains1。
提前致谢
答案 0 :(得分:6)
您从声明Tree happytree = ...
收到错误。看起来C风格的习惯隐藏在你的代码中,你试图以错误的方式声明一个类型的常量。
它只是happytree = ...
,编译器推断出类型。如果要明确指定它,可以像使用函数一样进行,并在单独的行上写happytree :: Tree
。
至于摆脱contains1
,它正在测试列表中任何树是否包含值,所以你可以这样摆脱它:
contains :: Tree -> Int -> Bool
contains (Node x []) y = x==y
contains (Node x as) y = x==y || any (`contains` y) as
我在这里使用部分语法来部分应用contains
;你可以改为写一个lambda \a -> contains a y
。
答案 1 :(得分:6)
虽然Sebastian的回答告诉您问题(类型声明属于他们自己的行),但请注意错误消息源于以下内容:
data Id Int = Id Int
Id x = Id 5
这完全有效,因为您使用模式Id x
进行绑定。它与
(x:_) = [5..]
但是,为了做到这一点,你需要一个数据构造函数,例如可以创建值的内容,例如Node
,而Tree
是类型的构造函数,它会创建(或者在本例中为是)类型。这就是为什么你最终得到这个相当神秘的错误信息的原因:
Not in scope: data constructor ‘Tree’ Perhaps you meant ‘True’ (imported from Prelude)
无论哪种方式,您都可以通过从Tree
移除Tree happytree
来解决此问题。
对于您的其他问题,请使用any
:
contains :: Tree -> Int -> Bool
contains (Node x as) y = x == y || any (`contains` y) as
请注意,elem
- 类似函数(在列表elem :: Eq a => a -> [a] -> Bool
上)通常首先使用谓词,最后使用容器,这使contains
的应用更容易:
contains :: Int -> Tree -> Bool
contains y (Node x as) = x == y || any (contains y) as