[Haskell-cafe] First go at reactive programming

Levi Stephen levi.stephen at optusnet.com.au
Thu Jan 17 04:54:14 EST 2008


Hi,

Below is a version that was aimed at getting rid of the (Handle,IO 
(Request a)) tuples and as a result made it easier to remove the IO 
monad from some types, but I don't think it removed it completely from 
any methods.

module Main where

import Control.Applicative
import Control.Concurrent
import Control.Monad

import Data.Reactive

import Network.BSD
import Network.HTTP
import Network

import System.IO

import Text.XHtml.Strict

type RequestHandler = Request -> Response

main = runHttpServer helloWorldHandler

helloWorldHandler :: RequestHandler
helloWorldHandler =  Response (2,0,0) "" [] . prettyHtml . helloWorldDoc

helloWorldDoc :: Request -> Html
helloWorldDoc rq =     header << thetitle << "Hello World"
                   +++ body   << (h1 << "Hello World" +++ p << show rq)

runHttpServer :: RequestHandler -> IO a
runHttpServer r = socketServer >>= runE . fmap (handleConnection r)

socketServer :: IO (Event Handle)
socketServer = withSocketsDo $ do
  (e,snk) <- mkEventShow "Server"
  sock    <- listenOn (PortNumber 8080)
  forkIO $ forever $ acceptConnection sock $ snk
  return e

handleConnection :: Handle -> RequestHandler -> IO ()
handleConnection h r =
  handleToRequest h >>= responseSend h . runRequestHandler r

handleToRequest :: Handle -> IO (Result Request)
handleToRequest = receiveHTTP

runRequestHandler :: RequestHandler -> Result Request -> Result Response
runRequestHandler r rq = rq `bindE` (Right . r)

responseSend :: Handle -> Result Response -> IO ()
responseSend h rsp = either print (respondHTTP h) rsp >> close h

acceptConnection :: Socket -> (Handle -> IO ()) -> IO ThreadId
acceptConnection s k = accept s >>= \(h,_,_) -> forkIO $ k h

instance Stream Handle where
  readLine   h   = hGetLine h >>= \l -> return $ Right $ l ++ "\n"
  readBlock  h n = replicateM n (hGetChar h) >>= return . Right
  writeBlock h s = mapM_ (hPutChar h) s >>= return . Right
  close          = hClose




More information about the Haskell-Cafe mailing list