Hacker News new | past | comments | ask | show | jobs | submit login

Hm... for anything real, you would need to provide good error reports, i.e. why did it fail to parse. Code like this looks pretty, but once you add in good error reports, I feel like it tends to look almost exactly the same as in an imperative language?





For a real use case, consider using a parser library. If you ignore the boilerplate import stuff, it's IMHO rather short and elegant - and not very imperative:

  {-# LANGUAGE OverloadedStrings #-}

  import Data.Text (Text)
  import Data.Void (Void)
  import qualified Data.Text as T
  import Text.Megaparsec
  import Text.Megaparsec.Char
  import qualified Text.Megaparsec.Char.Lexer as L

  type Parser = Parsec Void Text

  numParser :: Parser [Integer]
  numParser = L.decimal `sepBy` space1

  -- just for demonstration purposes - this will print an ugly debug string, it can be customised
  main = putStrLn $ show $ parse numParser "some-source-file.txt" "10 20  30 x"

  -- this would print "Right [10, 20, 30]"
  -- main = putStrLn $ show $ parse numParser "some-source-file.txt" "10 20  30"

  strSum :: String -> Either String Int
  strSum = fmap sum . mapM readEither . words

That doesn't exactly give a good error message, though:

  > strSum "10 20 x"
  Left "Prelude.read: no parse"
But yeah, I didn't remember "mapM". mapM f = sequence . fmap f, which is what I used.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: