如何解决ZipList 可以是分布式的吗?
Base 提供 ZipList,它只是 []
的包装器,其中 <*>
基于 zip
而不是笛卡尔积。这不是默认设置,因为它与 Monad []
实例不一致,但有些人认为它更直观,而且这两种行为在不同的上下文中都很有用。
Edward Kmett 提供了 Distributive,Traversable
的对偶。一个 Traversable 可以被映射/推送/分发到任何 Applicative Functor 中;可以从任何 Functor 中提取/分解一个 Distributive。 (由于我没有拆包的原因,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..]
。 - 我们可以将那个扩展到返回有限列表的函数;我们最终得到一个无限的部分函数列表。对我来说,这是不可接受的并不明显。在处理列表时,部分函数总是会出现。
- 但这意味着
distribute $ const [] ≅ repeat undefined
,这有点傻。 - 实例
Applicative ZipList
包含一个重要的设计决策:length (a <*> b) == min (length a) (length b)
(与错误或其他内容相反)。我们根本没有利用它。在我看来,我们可能是distribute = const []
。
- 直观
有人看到前进的道路吗?
如果部分函数的解释是“可接受的”,我们是否可以用比 distribute f = (\i -> (!! i) <$> f) <$> [0..]
更愚蠢的方式来概括?
解决方法
不,它不能是分布式的。
Pair
的明显 Distributive
实例如下所示:
instance Distributive Pair where
distribute vs = Pair (pFst <$> vs) (pSnd <$> vs)
现在让我们考虑列表实例。 (让我们暂时忽略 ZipList
噪声,假设基本列表具有 zippy 实例。)我们需要 distribute . distribute = id
。假设
x = distribute (Pair "" "a")
因此法律要求:
distribute x = Pair "" "a"
我们可以用distribute
的定义代替Pair
,得到:
Pair (pFst <$> x) (pSnd <$> x) = Pair "" "a"
这是一个问题,因为列表的 (<$>)
保留长度,这里我们要求它在提供相同参数时返回两种不同长度的答案。糟糕!
作为替代方案,您可能对 data Stream a = Cons a (Stream a)
感兴趣,它是保证无限列表的类型,可以Distributive
:
sHead :: Stream a -> a
sHead (Cons a _) = a
sTail :: Stream a -> Stream a
sTail (Cons _ as) = as
instance Distributive Stream where
distribute streams = Cons (sHead <$> streams) (distribute (sTail <$> streams))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。