Created
December 17, 2009 20:37
-
-
Save chriseidhof/259010 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> {-# 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