在Haskell,为什么没有一个TypeClass可以像列表一样的东西?

我正在读Learn You a Haskell,我想知道为什么这么多的事情都像一个列表,在Prelude中没有使用类型类的本机工具来设置:

“The bytestring version of : is called cons It takes a byte and a bytestring and puts the byte at the beginning. It’s lazy though, so it will make a new chunk even if the first chunk in the bytestring isn’t full. That’s why it’s better to use the strict version of cons, cons’ if you’re going to be inserting a lot of bytes at the beginning of a bytestring.”

为什么没有TypeClass可列表或提供:函数来统一Data.ByteString,Data.List,Data.ByteString.Lazy等等?这是有原因的,还是这只是传统Haskell的一个元素?使用:作为一个例子是一种低调,也从LYAH:

Otherwise, the bytestring modules have a load of functions that are analogous to those in Data.List, including, but not limited to, head, tail, init, null, length, map, reverse, foldl, foldr, concat, takeWhile, filter, etc.

ListLike包似乎提供您要找的。我从来没有理解为什么它不更受欢迎。

ListLike,Prelude中没有实现的一个原因是因为它不可能这样做没有调用一些语言扩展(多参数类型和fundeps或相关联的类型)。有三种容器要考虑:

>根本不关心其元素的容器(例如[])
>仅针对特定元素(例如,bytestrings)实施的容器
>对元素有多态性但需要上下文的容器
(例如Data.Vector.Storable,它将
保持任何类型与可存储
实例)。

这里有一个非常基本的ListLike风格的类,不使用任何扩展:

class Listable container where
  head :: container a -> a

instance Listable [] where
  head (x:xs) = x

instance Listable ByteString where --compiler error, wrong kind

instance Listable SV.Vector where
  head v = SV.head    --compiler error, can't deduce context (Storable a)

这里容器有* – > *。这将不适用于bytestrings,因为它们不允许任意类型;他们有种*。它也不适用于Data.Vector.Storable向量,因为类不包括上下文(Stoable约束)。

你可以通过更改你的类定义来解决这个问题

class ListableMPTC container elem | container -> elem where

要么

class ListableAT container where
  type Elem container :: *

现在容器有种*;它是一个完全应用的类型构造函数。也就是说,你的实例看起来像

instance ListableMPTC [a] a where

但你不再是Haskell98。

这就是为什么即使一个简单的Listable类型接口是不平凡的;当你有不同的集合语义来解释(例如队列)时,它会变得更难。另一个真正大的挑战是可变对不可变数据。到目前为止,我见过的每一个尝试(除了一个)通过创建一个可变接口和一个不可变的接口来解决这个问题。我知道的一个接口,它统一了两个是心灵弯曲,调用一堆扩展,并有相当差的性能。

附录:bytestrings

完全推测我的部分,但我认为我们被困住作为进化的产物bytestrings。也就是说,它们是低性能I / O操作的第一个解决方案,使用Ptr Word8与IO系统调用接口是有意义的。对指针的操作需要可存储,并且最有可能的是使得多态性工作所必需的扩展(如上所述)不可用。现在很难克服他们的势头。具有多态性的类似容器当然是可能的,storablevector包实现了这一点,但它不像任何地方流行。

可以bytestrings是多态而没有对元素的任何限制?我认为最近的Haskell有这个是Array类型。这不像低级IO的字节测试那么好,因为数据需要从指针解包到数组的内部格式中。此外,数据被装箱,这增加了显着的空间开销。如果你想要unboxed存储(更少的空间)和高效的接口C,指针是要走的路。一旦你有一个Ptr,你需要Storable,然后你需要在类型类中包含元素类型,所以你需要扩展。

话虽如此,我认为使用适当的扩展可用这本质上是任何单个容器实现(modulo可变/不可变API)的解决问题。更难的部分现在提出一个合理的类集合,可用于许多不同类型的结构(列表,数组,队列等),并且足够灵活,有用。我个人认为这是相对直接的,但我可能是错的。

http://stackoverflow.com/questions/3623612/in-haskell-why-isnt-there-a-typeclass-for-things-that-can-act-like-lists

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:在Haskell,为什么没有一个TypeClass可以像列表一样的东西?