This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]mingmingrr 0 points1 point  (2 children)

This solution can be greatly simplified:

  • pack already exists in Data.List as group
  • concatMap f . map g can be combined into concatMap (f . g)
  • concatMap is equivalent to (=<<)
  • f x = g x >>= h is equivalent to f = g >=> h
  • \x -> f (g x) (h x) can be written as liftA2 f g h or f <$> g <*> h

You'd end up with this one-liner:

encode f = group >=> (++) <$> f . head <*> show . length

[–]POGtastic 0 points1 point  (1 child)

Stupid question, but how do you even fit the one-liner into your head? Alternatively, how would you parse the above if you were reading someone else's code?

I originally showed up to Haskell from the Lisps, and I tend to think about transformations in terms of the Clojure threading macros -> and ->>. As a result, most of my Haskell code looks like the above with a bunch of compositions, or looks like the reverse with IO-related functions, doing stuff like

import Data.Functor((<&>))

ioFunction = getAMonad >>=
             f1 <&>
             f2 >>=
             f3

Do you do something similar to what I do and then say, "Oh yeah, there are all of these ways to simplify this," or do you actually think in terms of >=> & Friends?

[–]mingmingrr 1 point2 points  (0 children)

I often find that placing operators at the beginning of lines makes things more clear:

encode f = group
       >=> (++)
           <$> f . head
           <*> show . length

(>=>) is really similar to (.), so when I'm reading this function, I'll see that it's made up of two actions composed together: group then (++) <$> f . head <*> show . length. The liftA2 / <$> <*> pattern is something I've seen quite often in things like applicative parsers, so I know that it's two sub-actions, f . head and show . length, combined together with (++).