Short Code

Posted by lorne on June 21st, 2006 — Posted in General

One of the complaints I’ve heard about Haskell is that it makes your code shorter. I’m not quite sure how that’s a bad thing, but it occurred to me while looking at a algorithm I wrote in Ruby.

puts $_.chomp.gsub(/../) { |b| b.hex.to_s + "."}.chop

The algorithm takes an IP address compactly represented in hex and returns the dotted decimal form.

Parsec is wonderful! I’ve been using it for a tetrinet protocol decoder so that was the first thing on my mind.

main = do
  (h:_) <- getArgs
  case parse (count 4 hexbyte) "Arguments" h of
    Right r -> putStrLn $ tail $ concatMap (('.':) . show) r
    Left e -> fail $ "Invalid input\n" ++ (show e)

hexbyte :: Parser Int
hexbyte = count 2 hexDigit >>= return . read . ('0':) . ('x':)

Which seems fairly easy to follow and has some error reporting free from Parsec, but I figure a parser library might be overkill for this task.

Turning to more “raw” Haskell, mostly the useful functions in the Data.List library, gives

main = getArgs >>= putStrLn . concat . intersperse "." .
       map (show . readByte) .  unfoldr lf . head
       where
         readByte :: String -> Int
         readByte = read . ('0':) . ('x':)
         lf [] = Nothing
         lf t  = Just $ splitAt 2 t

They’re all following approximately the same algorithm of a mapping on every two characters. However the gsub(/../) { |b| … } appears to be a very compact notation which I have been unable to match.

No Comments »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment