arrowp-qq-0.3.0: examples/cgi/CGI.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# OPTIONS -F -pgmF arrowp-ext #-}
-- CGI library from Hughes's paper (s.10)
-- This is just an exploratory formulation: it type-checks, but
-- it doesn't actually do anything.
module CGI where
-- Note that this requires a special generalized version of the arrow
-- library, with a special class for first and associates.
import ArrowContext
data ScriptState
= Ask
| Comp (Either ScriptState ScriptState)
| First ScriptState String
data Input a = Initial a | Resume ScriptState String
data Output a = Final a | Suspend ScriptState String
newtype CGIFunctor a b c = CGI (a (Input b) (Output c))
example :: (ArrowChoice a, ArrowContext a String) => CGIFunctor a b String
example = proc z -> do
q <- ask -< "What is your question?"
ans <- ask -< q
returnA -< "The answer to \"" ++ q ++ "\" is " ++ ans
liftCGI :: ArrowChoice a => a b c -> CGIFunctor a b c
liftCGI f = CGI $ proc (Initial b) -> do
c <- f -< b
returnA -< Final c
ask :: ArrowChoice a => CGIFunctor a String String
ask = CGI $ proc x -> case x of
Initial q -> returnA -< Suspend Ask q
Resume Ask a -> returnA -< Final a
instance ArrowChoice a => Arrow (CGIFunctor a) where
arr f = CGI $ proc (Initial b) ->
returnA -< Final (f b)
CGI f >>> CGI g = CGI $ proc z -> case z of
Initial b -> enterf -< Initial b
Resume (Comp (Left s)) a -> enterf -< Resume s a
Resume (Comp (Right s)) a -> enterg -< Resume s a
where enterf = proc x -> do
y <- f -< x
case y of
Final c -> enterg -< Initial c
Suspend s q -> returnA -<
Suspend (Comp (Left s)) q
enterg = proc x -> do
y <- g -< x
returnA -< case y of
Final d -> Final d
Suspend s q ->
Suspend (Comp (Right s)) q
instance (ArrowChoice a, ArrowContext a d, Read d, Show d) =>
ArrowContext (CGIFunctor a) d where
first (CGI f) = CGI $ proc x -> do
let (b', d) = case x of
Initial (b, d) -> (Initial b, d)
Resume (First s v) a -> (Resume s a, read v)
c' <- f -< b'
returnA -< case c' of
Final c -> Final (c, d)
Suspend s q -> Suspend (First s (show d)) q
instance ArrowChoice a => ArrowChoice (CGIFunctor a) where
left (CGI f) = CGI $ proc x -> case x of
Initial (Left b) -> enterf -< Initial b
Initial (Right d) -> returnA -< Final (Right d)
Resume s a -> enterf -< Resume s a
where enterf = proc x -> do
y <- f -< x
case y of
Final c -> returnA -< Final (Left c)
Suspend s q -> returnA -< Suspend s q