如何在Haskell类型构造函数中定义参数类型?

时间:2016-10-26 06:43:19

标签: function haskell types

首先想象一下树的标准构造:

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

显然上面的代码并不好,但是我想到的那种事情就是一个例子。

如果我想要的是可能的,或者理想情况下如果还有其他方法可以解决这个问题,我很乐意听到它。重点是数据类型和功能的定义,而不仅仅是这个特定的问题。

谢谢!

2 个答案:

答案 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)