Blogged by Ujihisa. Standard methods of programming and thoughts including Clojure, Vim, LLVM, Haskell, Ruby and Mathematics written by a Japanese programmer. github/ujihisa

Monday, December 6, 2010

Writing Fibonacci Web Server in Haskell

A practice: implementing a web service which receives a number by URL parameter and returns the corresponding Fibonacci sequence number.

GET
http://localhost:8000/fib/10

returns

fib(10) = 55

I used Snap Framework.

$ mkdir snapfib
$ cd snapfib
$ snap init

This generates an empty snap project files. then

$ cabal install
$ snapfib

builds the codes and installs a command snapfib in your ~/.cabal/bin/snapfib. You may run the app locally with the default port 8000; you may open the default page, hello world, on your browser.

Then implement fib sequence, a utility function, and the controller/view. This allows you to get the Fibonacci sequence number just by URL parameter.

Below is the main routine code from the repository.

{-# LANGUAGE OverloadedStrings #-}
module Main where

import           Control.Applicative
import           Snap.Types
import           Snap.Util.FileServe
import           Text.Templating.Heist
import           Text.Templating.Heist.TemplateDirectory

import           Glue
import           Server
import           Data.ByteString.Char8 (pack, unpack)

fibs :: [Integer]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

fibInString :: Int -> String
fibInString n = "fib(" ++ show n ++ ") = " ++ show (fibs !! n)

main :: IO ()
main = do
    td <- newTemplateDirectory' "templates" emptyTemplateState
    quickServer $ templateHandler td defaultReloadHandler $ \ts ->
        ifTop (writeBS "hello world") <|>
        route [ ("foo", writeBS "bar")
              , ("fib/:n", fibHandler)
              ] <|>
        templateServe ts <|>
        dir "static" (fileServe ".")


fibHandler :: Snap ()
fibHandler = do
    param <- getParam "n"
    maybe (writeBS "must specify fib/n in URL")
          (writeBS . pack . fibInString . read . unpack) param

(writeBS . pack . fibInString . read . unpack) param is converting param :: Maybe ByteString into Int, getting a Fibonacci sequence number in String, converting into ByteString again, and passing it to writeBS function which is defined in Snap Framework.

It was not difficult or complicated to implement such a simple web service in Haskell as long as you have basic Haskell knowledges like Maybe Monad or String manipulations. The problem was, in my opinion, it took long time to build the web app. Every time you fix your code, you have to wait for the compilation before you access your web service.

No comments:

Post a Comment

Followers