Yosh
Yosh

Reputation: 2742

"Zippable" class for haskell?

In an attempt to get familiar with the great ideas such as Foldable, Functor, etc. I'm writing a data structure for 2*2 matrix. It isn't for real use, so I thought this naive implementation is a good start:

data Matrix2d a = M2 a a a a

I want this to be a Num instance

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)
    -- ....

This does not seem right. I don't want to type + five times for this obvious definition. Certainly there's room for more abstraction. I'd prefer something like

(+) = fzipWith (+) -- f does not mean anything here

This is actually easy to implement:

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)

however, I couldn't find anything ready-to-use in hoogle. I find it odd because this kind of abstraction seems quite natural. There's Foldable, there's Functor --- why not Zippable?

Questions:

Upvotes: 6

Views: 540

Answers (2)

Doug McClean
Doug McClean

Reputation: 14485

See the adjunctions package, and in particular Data.Functor.Rep.liftR2.

Your Matrix2 is a representable functor.

Upvotes: 3

MathematicalOrchid
MathematicalOrchid

Reputation: 62818

You can't do much with just Functor, but with Applicative you can do

fzipWith f za zb = f <$> za <*> zb

The default instance for Applicative [] won't do quite what you want; it will take every a with every b. But I believe there's a ZipList newtype somewhere that gives you an instance that zips the way you're expecting. (No, I don't know exactly where it lives.)

Note that this generalises to any number of arguments:

f <$> za <*> zb <*> zc <*> zd

so you don't need the zipWith, zipWith3, zipWith4, etc functions.

Upvotes: 8

Related Questions