12:42 pm, 31 Jul 07
run length encoding and arrows
Run length encoding in Haskell casually tosses in this bit:
Which produces RLE'd tuples:
But what's this
That is,
where the first component of the tuple is the length and the second is the head of the list.
What a peculiar but also imaginably useful operator! (Of course, in the arrows docs the application of this just to functions is the most basic of the many generalizations.)
encode = map (length &&& head) . groupWhich produces RLE'd tuples:
> encode "aaaabbaaa"
[(4,'a'),(2,'b'),(3,'a')]But what's this
&&& bit? It's from Control.Arrow, the implementation of arrows, which are reportedly a generalization of monads. The last time I tried to look at this was before I grokked monads so it's probably worth another look, but the superficial understanding needed here is that &&& runs two functions "in parallel" (not as in simultaneously, just in that they're not interacting) and produces a pair of their two outputs.That is,
> :t length &&& head
length &&& head :: [a] -> (Int, a)where the first component of the tuple is the length and the second is the head of the list.
What a peculiar but also imaginably useful operator! (Of course, in the arrows docs the application of this just to functions is the most basic of the many generalizations.)
(map 'list '(lambda (x y) (list x y)) '(a b c) '(1 2 3)) ==> ((a 1) (b 2) (c 3))I just wrote a little object serializer that does something really similar, iterating through various properties of the object and making appropriate string conversions. Only now I'm always going to wish I had Haskell. Thanks a lot, dude.
A slightly more readable solution...
encode = map (\x -> (length x, head x)) . groupalso seems to work, and has the benefit of being understandable by mortals ;-)
Re: A slightly more readable solution...
Yeah. The point of this post was just that the &&& operator just generalizes the (\x -> (foo x, bar x)) pattern. I think your way of explaining it was clearer, though. :)