首先想象一下树的标准构造:
data Tree k = Leaf | Node k (Tree k) (Tree k)
我想实现一个版本,我通过计算它来处理重复的条目,所以我有这样的类型:
data Tree k count = Leaf | Node k count (Tree k count) (Tree k count)
因此我的代码是:
tree_insert :: Ord k => k -> Tree k count -> Tree k count
tree_insert k Leaf = Node k 1 Leaf Leaf
tree_insert k (Node n count l r)
| k == n = Node n (count+1) l r
| k < n = Node n count (tree_insert k l) r
| k > n = Node n count l (tree_insert k r)
但是,如果您尝试使用此代码,则会收到以下错误:
无法从文字“1”中推断出(Num计数)
要修复它,我将函数的类型声明更改为:
tree_insert :: (Ord k, Num count) => k -> Tree k count -> Tree k count
然而,我遇到了进一步的问题。对我而言,似乎Haskell告诉我,如果没有Num count
,它不知道它应该是什么类型,因此当我在第一个模式中将其指定为1时,它会产生错误。 Num count
似乎不是解决问题的好方法。理想情况下,当我进行初始类型声明时,我应该能够定义类型计数,例如:
data Tree k count = Leaf | Node k count (Tree k count) (Tree k count)
where count is Int
显然上面的代码并不好,但是我想到的那种事情就是一个例子。
如果我想要的是可能的,或者理想情况下如果还有其他方法可以解决这个问题,我很乐意听到它。重点是数据类型和功能的定义,而不仅仅是这个特定的问题。
谢谢!
答案 0 :(得分:3)
这里有两种选择。更简单的方法就是不在count
类型上对Tree
进行参数化。
data Tree k = Leaf | Node k Int (Tree k) (Tree k)
tree_insert :: Ord k => k -> Tree k -> Tree k
tree_insert ...
或者,如果你有时想到自己需要更一般的树型,你可以坚持使用类型的synonyn。
data Tree k count = Leaf | Node k count (Tree k count) (Tree k count)
type TreeInt k = Tree k Int
tree_insert :: Ord k => k -> TreeInt k -> TreeInt k
tree_insert ...
答案 1 :(得分:1)
您的原始树类型已经完全参数化存储在每个节点的数据类型;您可以使用存储(k, Int)
值而不只是k
值的树。
data Tree k = Leaf | Node k (Tree k) (Tree k)
tree_insert :: a -> Tree (a, Int) -> Tree (a, Int)
tree_insert k Leaf = Node (k, 1) Leaf Leaf
tree_insert k (Node (n, count) l r)
| k == n = Node (n, count+1) l r
| k < n = Node (n, count) (tree_insert k l) r
| k > n = Node (n, count) l (tree_insert k r)