David Menendez zednenem at psualum.com
Thu Dec 9 22:31:14 EST 2004

```Conor McBride writes:
> Jan-Willem Maessen - Sun Labs East wrote:
> > Tomasz Zielonka wrote:
> >
> >>I found it useful recently, when I needed zip functions for Trees -
> >>this way I didn't have to define functions for 3 trees, 4 trees,
> >>and so on.
> >
> >
> > Note also that:
> >
> > repeat f `zwApply` xs  =  map f xs
> >
> > When cooking up my own collection-y things (including splittable
> > supplies, for example), I generally provide fmap and an equivalent
> > of zwApply (a generic repeat is not quite so simple or useful).
> > It's a nice little idiom, and a recommend it highly.
>                      ^^^^^
>
> Funny you should choose that word:
>
>
> saves me banging the same old drum.

Now that I think about it, you can generalize the trick I mentioned
elsewhere to work over any

> class Sequence f where
>   unit  :: a -> f a
>   (<*>) :: f (a -> b) -> f a -> f b
>
> liftN :: Sequence f => (f a -> b) -> a -> b
> liftN d f = d (unit f)
>
> suc :: Sequence f => (f b -> c) -> f (a -> b) -> f a -> c
> suc d f x = d (f <*> x)
>
> zero = id
>
> one :: Sequence f => f (a -> b) -> f a -> f b
> one = suc zero
>
> two :: Sequence f => f (a -> b -> c) -> f a -> f b -> f c
> two = suc one
>
>
> newtype L1 a = L1 { unL1 :: [a] }
> newtype L2 a = L2 { unL2 :: [a] }
>
>
> instance Idiom L1 where
>   unit x = L1 [x]
>   L1 fs <*> L1 xs = L1 [ f x | f <- fs, x <- xs ]
>
> instance Idiom L2 where
>   unit x = L2 (repeat x)
>   L2 fs <*> L2 xs = L2 (zipWith (\$) fs xs)

*Main> unL1 \$ liftN two (,) (L1 [1,2,3]) (L1 "abc")
[(1,'a'),(1,'b'),(1,'c'),(2,'a'),(2,'b'),(2,'c'),(3,'a'),(3,'b'),(3,'c')
]
*Main> unL2 \$ liftN two (,) (L2 [1,2,3]) (L2 "abc")
[(1,'a'),(2,'b'),(3,'c')]
--
David Menendez <zednenem at psualum.com> | "In this house, we obey the laws
<http://www.eyrie.org/~zednenem>      |        of thermodynamics!"
```