如果zip是合法类型类的方法,那么该方法呢?

时间:2018-08-18 15:31:01

标签: haskell typeclass

问题的原因 人们可能会说zipApplicative的一种方法,通常的例子是ZipList。我不满意,因为它不安全。我也对Align感到不满意,因为它由于包罗万象而变得过于复杂,并且对于常规情况而言不够具体。

合法类:Haskell中的某些类型类可能被称为 legacy 。这意味着它们带有必须满足的平等-阶级的法律。这些定律通常来自编程方面的范畴理论概念化。例如,Monad是通过同义类别理论设备对计算 (无论什么意思)的概念。

重叠的东西

示例:

没有足够的定律。这个概念的概念化是通过单曲面函子和相应的Applicative类型类实现的。但是,这有一个烦人的麻烦,因为通常有两种方法来定义Applicative,而这两种方法似乎都适用。为什么这样?我建议答案是“法律不足”

示例:

  • 用于算术:

    • Sum Monoid是实际的“内-monoid” 。仅对亲属事物合法。例如,您不能求和求和。
    • Product Monoid将维数ab的数目带到维数c的数目。乘以质量和力量是合法的,这使我们感到温暖。

    因此,可以根据类型推断出正确的monoid选择。

  • 对于列表:

    • 通常的direct sum列表是最安全的列表。它可平凡地处理任何有限数量的元素,并使用“对角过程” 定义(例如LogicT)对其共有限数量起作用。
    • ZipList定义显然是不安全的。它的定义是,给定两个不同长度的列表,将较长的列表裁剪为较短的列表。
    • 长度索引向量是通过要求证明给定列表长度相同的设备而允许对zip进行安全定义的设备。
  • 对于矩阵:

    • 通常的矩阵加法对维度均匀性有(非常合理)的要求,与上述长度索引向量相同。由于矩阵习惯性地用于各种现实世界的模拟中(例如3D图形),一旦矩阵开始被裁剪或填充为零,人们就会立即抱怨,因此ZipMatrix的定义类似于ZipList上面看起来没有吸引力。
    • 陌生人Kronecker multiplication使人联想到列表的直接乘积。并且它也接受Monad的定义。

两种情况:从这些示例中,它揭示出在我们称为“ monoid” ” monoidal的事物中有两种截然不同的观念函子” ,并且区别对于编程非常重要(也许不像纯理论),因为它可以消除混乱,消除不安全因素,并且主要是因为在每种情况下,都有两种完全不相关的算法可以运行


我认为单面函子的可逆性(也称为“强度” 很重要。但是,对Peano自然的求和和乘积等式运算的结果是无法区分的。 (我不确定它们是否可以被认为是类半角内生菌。)因此,我开始猜测类型的改变是其特征。物理量的乘法甚至不会将check键入为Monoid

PS 给出了Monad的一个实例,用于表示笛卡尔乘积上的长度索引矢量和Kronecker乘积上的矩阵,其中fold zip为{{1} }。

1 个答案:

答案 0 :(得分:8)

可以通过safe表示确切的压缩(如the Representable class包所称的那样)。与Representable相关的理论很多。就目前的目的而言,我们可以专注于...

  

如果Functorf见证了Representable的同构,则tabulate index(->) x

...和:

  

Haskell类型类别中可代表的endofunctors对读者monad是同构的,因此可以免费继承大量属性。

由于Representable函数对某种类型的函数是同构的(例如,同质对对Bool -> a是同构的,而无限流对Nat -> a是同构的),因此可以实现精确的压缩通过点按功能来压缩。这就是mzipRepMonadZip的{​​{1}}的默认实现)

mzip

MonadZip is a rather awkward class(主要是mzipRep :: Representable f => f a -> f b -> f (a, b) mzipRep as bs = tabulate (index as &&& index bs) 扩展的实现的一部分)中,它具有相关的法律,我将以非一语重述该法律:

  

信息保存:如果MonadComprehensions,则() <$ u = () <$ v

换句话说,如果munzip (mzip u v) = (u, v)u的形状相同,则v不会丢弃信息(因此mzip可以撤消信息)。 munzip暗示只有一种可能的形状,它使我们可以放下条件,从而获得精确的拉链。


相切注释:

  

Representable定义显然是不安全的。它的定义是,给定两个长度不同的列表,将较长的列表裁剪为较短的列表。

我会说,这取决于您要使用拉链的用途。有时您会想要或需要精确的压缩,而有时则不需要(例如,考虑使用ZipList将索引附加到列表的常见技巧);有时用填充而不是修剪是有意义的(参见leftaroundabout's comment)。这就是为什么我更喜欢将确切的压缩称为“精确”,而不是“安全”。

  

但是,这有一个烦人的麻烦,因为通常有两种方法来定义zip [0..],而这两种方法都看起来很合适。为什么这样?我建议答案是“法律不足”

我非常不同意这样的观点,即如果某个类允许某些数据类型使用多个实例,则该类未指定。我宁愿说,例如带有笛卡尔乘积的应用列表和带有拉链合的应用的列表是不同的结构,其特征在于相关的形态学-碰巧它们可以通过相同的数据类型在Haskell中表示。