# [Haskell-cafe] Composition and type magic

Sumit Sahrawat, Maths & Computing, IIT (BHU) sumit.sahrawat.apm13 at iitbhu.ac.in
Tue Feb 24 17:28:46 UTC 2015

```I didn't think of forcing xs to the end. I thought that I might be able to
convert the dot to something with type

(a -> b -> c) -> (b -> b) -> a -> b -> c

I tried flipping ((.).(.)) but got

(a -> b -> c) -> (c -> d) -> a -> b -> d

which is not what I wanted.

Thanks for the mini-tutorial. [?]

On 24 February 2015 at 18:58, Michael Orlitzky <michael at orlitzky.com> wrote:

> On 02/24/2015 12:57 AM, Sumit Sahrawat, Maths & Computing, IIT (BHU) wrote:
> > Thanks.
> > You've given me a good exercise in equational reasoning.
> >
> > I'm studying such things because I might start studying combinatory logic
> > (Smullyan's mockingbird book) soon.
> > It's a good exercise for the mind, and is very enjoyable with pencil &
> > paper.
> > Can you give me some more patterns like transducers (foldl foldl) and the
> > dot-dot-dot ( boobies, in your words :) ) example?
> >
>
> I cheated with the pointfree tool, but you can do it by hand, too. The
> only trick you need to know in this case is how to get the extra
> argument on the end. You start with,
>
>   conv xs = sum . zipWith (*) xs . reverse
>
> and obviously, you want the 'xs' on the end. So you want to switch the
> 'zipWith (*) xs' and 'reverse' somehow. Well, you can always flip the
> composition operator! Unfortunately it's no longer infix at that point,
> so it has to be written like,
>
>   conv xs = sum . (flip (.)) reverse (zipWith (*) xs)
>
> Now the secret is that putting an extra dot around the chain of
> functions takes it from a one-argument chain to a two-argument chain
> (where the first function in the chain eats the second argument). You
> can sort of see this in the type of 'sum' and '(sum .)':
>
>   ghci> :t sum
>   sum :: Num a => [a] -> a
>
>   ghci> :t (sum .)
>   (sum .) :: Num c => (a -> [c]) -> a -> c
>
> The second one essentially eats an argument by taking "something that
> will give me a list" instead of a list itself. You have to do the same
> thing with the '(flip (.)) reverse' part of the chain:
>
>   conv = (sum .) . (((flip (.)) reverse) .) zipWith (*)
>
> Now, since you've got '((flip (.)) reverse' in parentheses anyway, you
> can change it from a normal function application to a "section," i.e.
> these two are the same: (flip (.)) reverse == (. reverse). So you wind
> up with,
>
>   conv = (sum .) . (((. reverse) .) zipWith (*)
>
> Drop the useless parentheses,
>
>   conv = (sum .) . (. reverse) . zipWith (*)
>
> and now all that's left to do is pray that you aren't hanged for
> witchcraft.
>
> _______________________________________________
> Haskell-Cafe mailing list
>

--
Regards

Sumit Sahrawat
-------------- next part --------------
An HTML attachment was scrubbed...