Skip to content

Instantly share code, notes, and snippets.

@chriseidhof
Created December 17, 2009 20:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chriseidhof/259010 to your computer and use it in GitHub Desktop.
Save chriseidhof/259010 to your computer and use it in GitHub Desktop.
> {-# LANGUAGE GADTs #-}
> module Example where
> import qualified Data.Map as M
Let's assume that requests are simple |String|s.
> type Request = String
When running a web continuation, either the computation is completely finished,
or it displays a page with a continuation.
> data Result a =
> Done a
> | Step String (Web a)
In our module, a page is either a form of |a| or a basic webpage displaying
something. The 2 parameters for |Form| are it's display and its parsing
function.
> data Page a where
> Form :: String -> (String -> a) -> Page a
> Display :: String -> Page ()
A web continuation is just a function from |Request| to |Result|:
> newtype Web a = Web {runWeb :: Request -> Result a}
The |Web| newtype can easily be made an instance of |Monad|:
> instance Monad Web where
> return = Web . const . Done
> l >>= r = Web $ \req -> case (runWeb l req) of
> Done x -> runWeb (r x) req
> Step msg l' -> Step msg (l' >>= r)
From a single page we can calculate a |Result|:
> runPage :: Page a -> Result a
> runPage (Form msg parse) = Step msg (Web $ Done . parse)
> runPage (Display msg) = Step msg (return ())
We can derive two smart constructors that lift a |Page| directly into the |Web|
monad:
> display :: String -> Web ()
> display = constWebPage . Display
> form :: String -> (String -> a) -> Web a
> form m = constWebPage . Form m
Now we are ready to write an interactive evaluator for |Web|.
> runWebInteractively :: (Show t) => Web t -> IO ()
> runWebInteractively (Web w) = do putStr "Request> "
> ln <- getLine
> runWebInteractively' (w ln)
> runWebInteractively' :: (Show a) => Result a -> IO ()
> runWebInteractively' (Done a) = do print $ "Done: " ++ show a
> runWebInteractively' (Step msg cont) = do print $ "Message: " ++ msg
> runWebInteractively cont
> example = do name <- form "Hello, what's your name?" id
> [x,y] <- form "Enter two numbers seperated by a space:" (map read . words)
> display $ name ++ ", the sum is: " ++ show (sum' x y)
Run the example in GHCi:
> runExample = runWebInteractively example
Finally, some helper functions:
> constWebPage = Web . const . runPage
> sum' :: Int -> Int -> Int
> sum' = (+)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment