haskell类型类中的多个类型参数

时间:2008-11-21 15:46:22

标签: haskell typeclass

我正在尝试在Haskell98中做一些抽象但不知道该怎么做。

我想要做的是为可以转换为列表的类型定义一个类。

toList :: a -> [b]

但我不知道如何为这个方法定义一个类。我提出了以下三个想法:

class ToList a b where
    toList :: a -> [b]

class ToList a where
    toList :: a -> [b]

class ToList a where
    toList :: a b -> [b]

第一个不起作用,因为Haskell98不允许多个参数类。

第二个不起作用,因为b依赖于a而不能为每个b实现。

第三个也不起作用,因为我不知道如何使用'b'不是最后一个类型参数的类型来实现类。

data HTree a b = Nil | Node a b (HTree a b) (HTree a b)

toList Nil = []
toList Node x y l r = toList l ++ [(x,y)] ++ toList r

toList Nil = []
toList Node x y l r = toList l ++ [x] ++ toList r

我该怎么做?

3 个答案:

答案 0 :(得分:9)

另请参阅标准库中的Data.Foldable,它为任何toList实例提供Foldable函数。 Foldable需要一些复杂的实例化,但这将是一个好习惯。作为奖励,您的HTree类型与文档中的示例实例几乎完全相同。

此外,我建议您将HTree更改为:

data HTree a = Nil | Node a (HTree a) (HTree a)

然后使用HTree (a,b)代替HTree a b。这个单参数版本可以更容易地与标准类型和实例组合,并且它可以更多地达到正在发生的事情,因为它以相同的方式依赖于两个参数。它也是Functor,定义这样的实例会使这种类型非常适合使用。

答案 1 :(得分:4)

我建议Type classes are not as useful as they first seem - 如果推定的类只有一个接口方法,请考虑声明一个函数类型。我也来自OO背景,发现我花了太多时间试图让“课堂”意味着我认为的意思,当我真的应该使用“数据”时。

只需编写你的toList'功能然后'解除'它就可以对你的数据结构进行操作。事实上,备受赞誉的Yet Another Haskell Tutorial经历了一次广泛的练习,展示了它是如何完成的,并以二叉树为例。升力的好处在于它区分了什么是重要的 - 数据类型的结构,而不是toList'的实现 - 所以一旦完成提升以执行'按顺序遍历数据类型',你可以使用电梯来实现做任何事 - toList,print等等。支持toList不是数据结构的重要部分,因此它不应该在类声明中 - 重要的部分是如何遍历数据结构。

答案 2 :(得分:-1)

您可能希望为类ToList选择最后一个选项,并创建ToList的(HTree a)实例。然后toList有类型 (HTree a b) -> [b],而不是(HTree a b) -> [(a,b)]。我假设你认为是“关键”而b是“价值”类型。

class ToList a where
    toList :: a b -> [b]

data HTree a b = Nil | Node a b (HTree a b) (HTree a b)

instance ToList (HTree a) where
    toList Nil = []
    toList (Node x y l r) = toList l ++ [y] ++ toList r

test = toList (Node "a" 1 (Node "b" 2 Nil Nil) Nil)
-- test == [2,1]
相关问题