在尝试熟悉的伟大的想法,例如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呢?
问题:
你不能做很多事情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,等功能.