Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Zippable" class for haskell?

Tags:

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:

  • Is there any module that provides this functionality?
  • If not (I believe this is the case), what options do I have? Is defining my own class the best choice, or is there any better alternative?
like image 336
Yosh Avatar asked Jun 30 '15 16:06

Yosh


2 Answers

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.

like image 73
MathematicalOrchid Avatar answered Sep 22 '22 12:09

MathematicalOrchid


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

Your Matrix2 is a representable functor.

like image 40
Doug McClean Avatar answered Sep 19 '22 12:09

Doug McClean