为什么Haskell [](列表)不是类型类?

问题描述 投票:6回答:2

我正在编写一个Haskell函数,它以列表作为输入。也就是说,没有理由它不能成为队列或出队,或任何允许我访问其“头部”及其“尾部”(并检查它是否为空)的东西。所以[a]输入类型似乎太具体了。但是AFAIK没有标准的库类型类可以捕获这个接口。当然,我可以将我的函数包装在Data.Foldable.toList中并使其变为多态wrt可折叠,但这看起来不太正确(惯用)。

为什么没有标准的列表类型类? (为什么Haskell中的“容器”类型层次结构比我认为应该更少?)或者我错过了必要的东西?

list haskell types interface typeclass
2个回答
13
投票

给定的代数数据类型可以表示为其变形,一种称为Church encoding的变换。这意味着列表与他们的foldr同构:

type List a = forall b. (a -> b -> b) -> b -> b

fromList :: [a] -> List a
fromList xs = \f z -> foldr f z xs

toList :: List a -> [a]
toList l = l (:) []

但qazxsw poi也是qazxsw poi的特征。你可以用foldr来定义qazxsw poi,反之亦然。

Foldable

foldMap表征列表并不奇怪,因为列表是一个免费的幺半群。)换句话说,foldr基本上给你foldMap f = foldr (mappend . f) mempty foldr f z t = appEndo (foldMap (Endo . f) t) z 作为一个类。 foldMap :: Monoid m => (a -> m) -> [a] -> m的实例有一条通过它们的“路径”,可以走路给你一个清单; Foldable类型至少具有与列表一样多的结构。


关于你的疑虑:

它不像toList有函数Foldable / Foldable / Foldable,这是我会发现更直观的。

head是你的tail,你可以用isEmpty直接定义(安全版)null :: Foldable t => t a -> Bool

isEmpty

在我看来,head有点棘手。 an appropriate choice of Monoid甚至对任意类型都意味着什么并不明显。你当然可以写head :: Foldable t :: t a -> Maybe a head = getFirst . foldMap (First . Just) (通过tailing然后解散),但我认为定义tail的任何类型tail :: Foldable t => t a -> Maybe [a]必然在结构上类似于列表(例如toList)。此外,根据我的经验,绝大多数你认为你需要访问列表的T的情况毕竟是折叠。

也就是说,抽象不可靠的类型偶尔会有用。例如,tail :: T a -> Maybe (T a)为(单态)标记流定义了一个Seq类,用作解析器的输入。


5
投票

问题

让你的问题更具体,让我们问:

为什么不是类型类

tail

megaparsec图书馆?

一个答案

此类仅适用于有序的线性容器。 Streamclass HasHeadAndTail t where head :: t a -> Maybe a tail :: t a -> Maybe (t a) isEmpty :: t a -> Bool baseMapSet都不是实例。我甚至反对将HashMapHashTable作为一个实例,因为这个结构确实有两个可能的“头”。

关于这个类的一个实例,我们还可以说什么呢?我认为唯一的属性是如果Tree是假的那么SeqDList应该是非isEmpty。因此,isEmpty甚至不应该在类中,而是一个函数head

所以我的答案是:

  • 这个类在缺乏实例的情况下缺乏实用性。
  • 这个类缺乏有用的属性,缺乏属性的类经常被劝阻。
© www.soinside.com 2019 - 2024. All rights reserved.