Haskell中是否有可压缩的类?

6

为了熟悉像FoldableFunctor等伟大的想法,我正在编写一个二维矩阵的数据结构。虽然它并不是真正的使用,但我认为这个天真的实现是一个不错的开始:

data Matrix2d a = M2 a a a a

我希望这是一个Num实例。
instance Num a => Num (Matrix2d a) where
    (M2 a0 b0 c0 d0) + (M2 a1 b1 c1 d1) = M2 (a0+a1) (b0+b1) (c0+c1) (d0+d1)
    -- ....

这似乎不太对。我不想为这个显然的定义输入五次“+”。肯定有更多的抽象空间。我更喜欢像这样的东西
(+) = fzipWith (+) -- f does not mean anything here

这实际上很容易实现:
class Zippable z where
    fzipWith :: (a -> b -> c) -> z a -> z b -> z c

instance Zippable Matrix2 where
    fzipWith f (M2 x y z w) (M2 a b c d) = M2 (f x a) (f y b) (f z c) (f w d)

然而,我在hoogle中找不到任何现成的内容。我觉得这很奇怪,因为这种抽象似乎很自然。有Foldable,有Functor——为什么没有Zippable呢?

问题:

  • 是否有任何模块提供此功能?
  • 如果没有(我相信是这种情况),我有哪些选择?定义自己的类是最好的选择,还是有更好的选择?

1
学习Haskell:http://learnyouahaskell.com/functors-applicative-functors-and-monoids - AJF
2
这不是非常实用的答案,但是F-代数为获取像(+)这样的函数提供了非常规则的结构。 - luqui
2个回答

8

只有 Functor 是不能做太多事情的,但是通过使用 Applicative,你可以做更多的事情。

fzipWith f za zb = f <$> za <*> zb
Applicative []的默认实例并不能完全满足你的需求;它会取每个a和每个b。但我相信有一个ZipList新类型,可以给你期望的ZIP实例。(不,我不知道它在哪里。)
请注意,这适用于任何数量的参数:
f <$> za <*> zb <*> zc <*> zd

所以你不需要使用zipWithzipWith3zipWith4等函数。

在IT技术方面,这些函数可能不太常见。

你能添加一个实现的例子吗?我根据你的建议写了这个(https://gist.github.com/anonymous/417585e7f6d54ddfc7fd),这样可以吗? - Yosh
1
向量的默认 Applicative 实例编码了压缩。翻译成 Haskell 很简单。 - effectfully

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接