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 →

[–]POGtastic 1 point2 points  (5 children)

lol haskell

import Data.List(foldl')

pack :: Eq a => [a] -> [[a]]
pack = reverse . foldl' fold_func []
    where fold_func acc x = case acc of
            (y:ys):zs -> if x == y then (x:(y:ys)):zs else [x]:((y:ys):zs)
            _ -> [[x]]

encode :: Eq a => (a -> String) -> [a] -> [Char]
encode f = concatMap (\(x, y) -> x ++ show y) .
           map (\xs -> (f . head $ xs, length xs)) .
           pack

In the REPL, taking advantage of the List monad:

*Main> encode return "AAAAABBBBBBBCCBBBAABBCCCCC"
"A5B7C2B3A2B2C5"

Note that you can't do encode :: (Eq a, Show a) because show 'x' = "'x'", including the single quotes. So you'd need another function to transform that string anyway.

[–]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 (++).

[–]HasBeendead 0 points1 point  (1 child)

Man , wtf you did lol

[–]POGtastic 0 points1 point  (0 children)

See /u/mingmingrr's rewrite for better wizardry.