9

我正在尝试在 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

我该怎么做这样的事情?

4

3 回答 3

9

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

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

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

然后使用HTree (a,b)而不是HTree a b. 这个单参数版本将更容易与标准类型和实例组合,并且它更能说明正在发生的事情,因为它以相同的方式依赖于两个参数。它也是一个Functor, 并且定义这样一个实例将使这种类型非常好用。

于 2008-11-23T07:11:24.067 回答
4

我建议Type 类不像它们最初看起来那样有用- 如果假定的类只有一个接口方法,请考虑改为声明一个函数类型。我也来自 OO 背景,发现我花了太多时间试图让“类”意味着我认为的意思,而实际上我应该使用“数据”。

只需编写您的 toList' 函数然后“提升”它以对您的数据结构进行操作就容易得多。事实上,广受好评的Yet Another Haskell 教程通过大量练习展示了它是如何完成的,并使用二叉​​树作为示例。提升的好处在于它区分了重要的东西——数据类型的结构,而不是 toList 的实现——所以一旦提升执行“按顺序遍历数据类型”,你就可以使用提升来做任何事情 - toList、打印等等。支持 toList 不是数据结构的重要部分,所以不应该在类声明中——重要的部分是如何遍历数据结构。

于 2008-11-21T21:10:37.557 回答
-1

您可能希望为 ToList 类选择最后一个选项,并创建(HTree a)ToList 的实例。然后toList有类型 (HTree a b) -> [b],不是例子(HTree a b) -> [(a,b)]。我假设您将 a 视为“键”,将 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]
于 2008-11-22T11:27:18.920 回答