Skip to content

Instantly share code, notes, and snippets.

@nathanic
Created August 31, 2012 01:05
Show Gist options
  • Save nathanic/3547089 to your computer and use it in GitHub Desktop.
Save nathanic/3547089 to your computer and use it in GitHub Desktop.
Explanatory version of the line-reversing Haskell one-liner
-- a more verbose and explanatory version of this one-liner
-- main = interact $ unlines . map reverse . lines
-- we're going to use some library functions:
-- lines :: String -> [String]
-- unlines :: [String] -> String
-- reverse :: [a] -> [a]
-- reverse works on arbitrary lists, and Strings are [Char].
-- let ... in allows you to bind names to values,
-- scoped over the expression in the 'in' clause.
-- these are not variables, because they cannot vary.
-- The type annotations (::) below are optional,
-- but added for clarity.
reverseEachLine :: String -> String
reverseEachLine input =
let inputLines :: [String]
inputLines = lines input
reversedLines :: [String]
reversedLines = map reverse inputLines
output :: String
output = unlines reversedLines
in output
-- another library function:
-- interact :: (String -> String) -> IO ()
-- expects a pure function that [lazily] computes a transformation
-- on strings, streaming the output to stdout. interact uses
-- that function to produce an action that performs IO.
-- The entry point to haskell programs is `main`,
-- which must be an action that performs IO.
-- Haskell distinguishes pure functions from actions
-- that can have side-effects. IO is the most general
-- type of side effect, but it's possible to constrain code
-- to produce very specific kinds of effects.
-- In a sense, Java statements are effectively always actions in IO,
-- because there are no static constraints on what code can
-- have side effects.
main :: IO ()
main = interact reverseEachLine
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment