Base 提供ZipList,它只是[]
where <*>
is basedzip
而不是笛卡尔积的包装器。这不是默认设置,因为它与实例不一致Monad []
,但有些人发现它更直观,并且这两种行为在不同的上下文中都很有用。
Edward Kmett 提供Distributive,即Traversable
. Traversable 可以映射/推送/分发到任何 Applicative Functor;可以从任何 Functor 中提取/分解分布。(由于我没有解包的原因,distribute
不需要外层是Applicative。)
长度索引列表是 Distributive,并按照您的期望工作。具体来说,他们的 Applicative 实例基于zip
,就像ZipList
!这表明ZipList
也可能是Distributive
,这将是有用的。
文档Distributive
说明了任何实例都必须为真的两件事:
(->) x
“对于某些人来说,它 [必须] 同构x
。”- 列表与偏函数同构
Int ->
。
- 列表与偏函数同构
- “[它]需要有一种方法来持续压缩可能无限数量的自身副本。”
- 这或多或少是raison d'être的存在理由
ZipList
。
- 这或多或少是raison d'être的存在理由
这够好吗?今天下午我花了几个小时试图写作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..]
。 - 我们可以将其扩展到返回有限列表的函数;我们最终得到一个无限的偏函数列表。这对我来说并不明显,这是不可接受的。使用列表时,部分函数会一直出现。
- 但这意味着
distribute $ const [] ≅ repeat undefined
,这有点愚蠢。 - 该实例
Applicative ZipList
包含一个重要的设计决策:(length (a <*> b) == min (length a) (length b)
而不是错误或其他)。我们根本没有利用它。我可以看到我们可能会的方式distribute = const []
。
- 直觉
有没有人看到前进的道路?
distribute f = (\i -> (!! i) <$> f) <$> [0..]
如果部分函数解释是“可接受的” ,我们能否以比