haskell的"Zippable"课程?

Yos*_*osh 6 haskell

在尝试熟悉的伟大的想法,例如Foldable,Functor等我写的数据结构为2×2矩阵.它不是真正的用途,所以我认为这个天真的实现是一个良好的开端:

data Matrix2d a = M2 a a a a
Run Code Online (Sandbox Code Playgroud)

我希望这是一个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)
    -- ....
Run Code Online (Sandbox Code Playgroud)

这似乎不对.我不想+为这个明显的定义键入五次.当然还有更多抽象的空间.我更喜欢像

(+) = fzipWith (+) -- f does not mean anything here
Run Code Online (Sandbox Code Playgroud)

这实际上很容易实现:

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)
Run Code Online (Sandbox Code Playgroud)

但是,我找不到任何可以在hoogle中使用的东西.我发现它很奇怪,因为这种抽象似乎很自然.有Foldable,有Functor- 为什么不Zippable呢?

问题:

  • 有没有提供此功能的模块?
  • 如果没有(我相信是这种情况),我有什么选择?定义我自己的班级是最好的选择,还是有更好的选择?

Mat*_*hid 7

你不能做很多事情Functor,但Applicative你可以做到

fzipWith f za zb = f <$> za <*> zb
Run Code Online (Sandbox Code Playgroud)

默认实例Applicative []不会完全符合您的要求; 这将需要每一个 a每一个 b.但是我相信ZipList某个地方有一个新类型会给你一个拉链的方式.(不,我不知道它到底在哪里.)

请注意,这可以推广到任意数量的参数:

f <$> za <*> zb <*> zc <*> zd
Run Code Online (Sandbox Code Playgroud)

所以你不需要zipWith,zipWith3,zipWith4,等功能.