Do You Even Lift?

    Lifting is a concept that allows the programmer to take a function that operates on a value, and change it into new function that only works on a wrapped version of that value. Lifting is the kind of thing that isn’t easy to explain, so i’ll give you some examples.

    At it’s simplest, fmap is lifting. It takes a function, and a functor, and returns another functor. But it can be partially applied like so:

    data Pair a = Pair a a deriving Show

    instance Functor Pair where
        fmap f (Pair x y) = Pair (f x) (f y)

    liftPair :: (a -> b) -> Pair a -> Pair b
    liftPair = fmap
    incPair :: Pair Int -> Pair Int
    incPair = liftPair (+1)

    First, we define the Pair type and make it a functor. Then, we make our lifting function, which is essentially just fmap, but only for pairs. It takes a function that takes two parameters (a binary operator) and a Pair of a's, and returns a Pair of b's. Now we can use that lifting function to make an increment operator that only works on values that are wrapped in Pair. Neat! 

    Monads can also be used in conjuction with lifting. 

    import Control.Monad
    plusList :: [Int] -> [Int] -> [Int]
    plusList = liftM2 (+)

    LiftM2 promotes a regular binary operator into one that operates on Monads. In this particular example, it takes a deterministic addition operator and changes it into a non-deterministic addition operator. If you add two lists, you’ll get another list, if you add a list with nothing, you’ll get nothing. Sort of like a chain of »='s. 

   Try doing these two expressions and seeing the differences.

    [1,2,3,4,5] ++ [6,7]
    [1,2,3,4,5] `plusList` [6,7]
    [1,2,3,4,5] ++ []
    [1,2,3,4,5] `plusList` []

Real World Parallelism: No More Jingles

    Although it is fun to play around with concurrent programming in Haskell, using it to solve a problem is fun too. Imagine, we have a program that asks a user to enter a file, compresses it, then asks for another file to compress - until the user enters an E.O.F character or a whitespace character. But how do we make the program ask for another file immediately, without the user having to wait for the compression to finish?

    import Control.Concurrent (forkIO)
    import Control.Exception
    import qualified Data.ByteString.Lazy as L
    import System.Console.Readline (readline)
    import Codec.Compression.GZip (compress)

    main = do
        input <- readline "Enter a file to compress>"
        case input of
          Nothing -> return ()
          Just "" -> return ()
          Just name -> do
               handle (print :: SomeException -> IO ()) $ do
                 content <- L.readFile name
                 forkIO (compressFile name content)
                 return ()
      where compressFile name = L.writeFile (name ++ ".gz") . compress

    First, let’s look at the imports. Control.Concurrent we need for forkIO. Control.Exception we need for readable error messages. We need Data.Bytestring.Lazy so we can make sure that the only thing the main thread is doing is opening the file. The reading is left up to the other thread. System.Console.Readline is her so we can use the versitile readLine function. And last but not least, Codec.Compression.Gzip is for actually compressing the files the user enters.

    Next, let’s analyse the code. The first thing the program does is ask the user for a filename. If it is an E.O.F or an empty string, we just return nothing. Otherwise, we call the input name. If the user inputs a non-existent filename, than handle will print a nice exception. Otherwise, the program lazily (L.) reads the file. So no information is stored, just a promise to do that later.

    All the real work is left to the new thread, which compresses the file by giving the name and content to the compressFile function. This function takes two parameters: (even though functions really only take one parameter in Haskell) the file’s name and content. It adds ".gz" to the filename, and compresses the file’s content. Only when it gets up to this step is when it reads the lazy byte-string.

    Because compressFile is written in point-free style, the second parameter is invisible. It could just as well be written like this:

    compressFile name insides = L.writeFile (name ++ ".gz") . compress insides

Parsing Party - Attoparsec

    Parsing is when you take a string and turn it into a bunch of usable data. Attoparsec is a popular parsing library that gives Haskell a bunch of neat parsing functions. Another library that might actually be more popular is Parsec, but it’s a heck of a lot slower.

    Haskell is really good at parsing. Like, faster than C++ good.

    {-# LANGUAGE OverloadedStrings #-}
    import Data.Attoparsec.Char8
    import Data.Word

    data IP = IP Word8 Word8 Word8 Word8 deriving Show
    parserIP :: Parser IP 
    parserIP = do
        n1 <- decimal
        char '.'
        n2 <- decimal
        char '.'
        n3 <- decimal
        char '.'
        n4 <- decimal
        return $ IP n1 n2 n3 n4

    main :: IO ()
    main = print $ parseOnly parserIP ""

    This code will parse through a IP address as a string, then spit out four numbers, 123, 45, 67, and 255. Pretty basic, but that’s what a parser ultimately does.

    First, we import the stuff that we need to parse an 8-bit ASCII character. Hence, Attoparsec.Char8. Then, we define parserIP, which defines a parser for our custom IP type. We use return at the end to inject our decimal values into an IP type. Then main uses Attoparsec’s parseOnly to apply parserID to the IP string.

    A tad confusing, but parsing is a crucial element in internet logging. Also, how do you think your text editor or IDE knows what the heck your writing?

Pa-ra-llel, Ha-a-skell!

An example of parallel processing in Haskell using Control.Concurrent:

        import Control.Concurrent
        import Control.Monad
        import System.IO
        main = do
            hSetBuffering stdout NoBuffering
            forkIO $ replicateM_ 1000 (putStr " This ")
            replicateM_ 1000 (putStr " That ")

    This code is gonna print a bunch of “This” and “That”. But the cool thing is, GHC is gonna do them at the same time. Woah. That’s called concurrency: forkIO creates a new thread that runs at the same time as everything else. Try running it, it looks really cool.

Yesod: Can Haskell Do Everything?

    Yesod is a Haskell Web Framework, for creating dynamic web pages in haskell. Sort of like Ruby on Rails for Ruby or Symphony for PHP. Also see Snap or Happstack: two other, less popular but not necessarily less functional, Haskell frameworks.

Here’s some code that makes an extraordinarily simple website.

    {-# LANGUAGE OverloadedStrings     #-}
    {-# LANGUAGE QuasiQuotes           #-}
    {-# LANGUAGE TemplateHaskell       #-}
    {-# LANGUAGE TypeFamilies          #-}
    import Yesod

    data Links = Links

    mkYesod "Links" [parseRoutes|
    / HomeR GET
    /page1 Page1R GET
    /page2 Page2R GET

    instance Yesod Links

    getHomeR  = defaultLayout [whamlet|<a href="@{Page1R}">Go to page 1!|]
    getPage1R = defaultLayout [whamlet|<a href="@{Page2R}">Go to page 2!|]
    getPage2R = defaultLayout [whamlet|<a href="@{HomeR}">Go home!|]

    main = warp 3000 Links