content: -----------------------------------------------------------------------------
  --
  -- A Haskell formlet is the combination of a parameter parser to read input plus a writer to generate HTTP
  -- output
  --
  -- I use this similarity to create parsec-like combinators that use the formlet monad in MFlow
  --(the View monad) to parse the web service parameters and to generate the output.
  --
  -- This service below implements a service that sum or multiply two Integers.
  --
  -- > parserService :: View Html IO ()
  -- > parserService=
  -- >        do rest "sum"  ; disp $ (+) <$> wint "t1" <*> wint "t2"
  -- >    <|> do rest "prod" ; disp $ (*) <$> wint "t1" <*> wint "t2"
  -- >    <?> do -- blaze Html
  -- >           h1 << "ERROR. API usage:"
  -- >           h3 << "http://server/api/sum?t1=[Int]&t2=[Int]"
  -- >           h3 << "http://server/api/prod?t1=[Int]&t2=[Int]"
  -- >   where
  -- >   asks w= ask $ w >> stop
  -- >   wint p= wparam p :: View Html IO Int
  --
  -- Can be called with:
  --
  -- > mainParser  = runNavigation "apiparser" . step . asks (parserService >> stop)
  --
  -- or
  --
  -- > mainParser =do
  -- >   addMessageFlows[("apiparser",wstateless  parserService)]
  -- >   wait $ run 80 waiMessageFlow
  -----------------------------------------------------------------------------
  
  module MFlow.Forms.WebApi (
  restp, rest, wparam, disp,(<?>)
  ) where
  import MFlow.Forms.Internals
  import MFlow.Forms(stop,(++>))
  import Control.Monad.State
  import Data.Typeable
  import Data.Monoid
  -- | Get the next segment of the REST path. if there is no one or if the data does not match
  -- with the type expected, then it return invalid.
  --  Therefore a monadic sequence in the View monad will not continue
  restp :: (Monad m,Functor m, FormInput v,Typeable a,Read a) => View v m a
  restp =  View $ do
     mr <- getRestParam
     return $ FormElm mempty mr
  
  
  
  -- | Check that the next rest segment has a certain value. It return invalid otherwise.
  -- therefore a monadic sequence in the View monad will not continue
  rest v= do
     r <- restp
     if r==v then return v
      else
       modify (\s -> s{mfPagePath= reverse . tail . reverse $ mfPagePath s}) >> stop
  
  -- | Get a parameter from a GET or POST key-value input.
  wparam par= View $ do
     mr <- getKeyValueParam par
     return $ FormElm mempty mr
  
  -- | append to the output the result of an expression
  dispv :: (Monad m, FormInput v) => View v m v -> View  v m ()
  dispv w= View $ do
     FormElm f mx <- runView w
     case mx of
       Nothing -> return $ FormElm f Nothing
       justx@(Just x) -> return $ FormElm (f <> x) $ return ()
  
  
  -- | append to the output the result of an expression
  disp :: (Monad m, FormInput v, Show a) => View v m a -> View  v m ()
  disp w= View $ do
     FormElm f mx <- runView w
     case mx of
       Nothing -> return $ FormElm f Nothing
       justx@(Just x) -> return $ FormElm (f <>fromStr (show x)) $ return ()
  
  -- | error message when a applicative expression do not match
  infixl 3 <?>
  (<?>) w v= View $ do
    r@(FormElm f mx) <- runView w
    case mx of
      Nothing -> runView $ v ++> stop
      Just _ -> return r
  