【发布时间】:2021-07-20 00:54:03
【问题描述】:
Base 提供ZipList,它只是[] 的包装器,其中<*> 基于zip 而不是笛卡尔积。这不是默认值,因为它与 Monad [] 实例不一致,但有些人觉得它更直观,并且这两种行为在不同的上下文中都很有用。
Edward Kmett 提供Distributive,Traversable 的双重性。 Traversable 可以映射/推送/分发到任何 Applicative Functor;可以从任何 Functor 中提取/分解分布。 (由于我没有解包的原因,distribute 不需要外层是Applicative。)
Length-indexed lists are Distributive,并按照您的预期工作。具体来说,他们的 Applicative 实例基于zip,就像ZipList!这表明ZipList 也可以是Distributive,这会很有用。
Distributive 的文档注意两点对于任何实例都必须正确:
-
“对于某些
x,它[必须] 与(->) x同构。”- 列表同构于部分函数
Int ->。
- 列表同构于部分函数
-
“[它]需要有一种方法来持续压缩可能无限数量的自身副本。”
- 这或多或少是
ZipList的存在理由。
- 这或多或少是
这样就够了吗?今天下午我花了几个小时试图写instance Distributive ZipList where distributive = ... 并不能完全让它工作。对于大多数函子f ZipList a,distribute f 有一个明显的含义,尽管我担心这可能只是因为我没有考虑足够的非-可遍历函子。
-
Maybe很棘手;distribute Nothing应该是[]还是repeat Nothing?但是distribute是sequenceA的对偶,Traversable Maybe实例说它应该是repeat Nothing。 -
(->) e可能会破坏交易。- 直观
distribute $ const (repeat x) = repeat (const x)。 - 我们可以将其扩展到任何保证返回无限列表的函数;有点像
(\i -> (! i) <$> f) <$> [0..]。 - 我们可以将 that 扩展到返回有限列表的函数;我们最终得到了一个无限的 partial 函数列表。这对我来说并不明显,这是不可接受的。使用列表时,部分函数会一直显示。
- 但这意味着
distribute $ const [] ≅ repeat undefined,这有点傻。 - 实例
Applicative ZipList包含一个重要的设计决策:length (a <*> b) == min (length a) (length b)(而不是错误或其他)。我们根本没有利用它。我可以看到我们可能会是distribute = const []。
- 直观
有人看到前进的方向吗?
如果部分函数解释是“可接受的”,我们能否以比distribute f = (\i -> (!! i) <$> f) <$> [0..] 更简单的方式对其进行概括?
【问题讨论】:
标签: haskell applicative traversable