MyNixOS website logo
Description

A transformer for generic requests.

An MTL-style monad that can be used to perform requests. Using RequestT simplifies writing generic middleware.

request-monad

Hackage

This library exports a monad that can be used to abstract a request sending/response handling pattern. It can be used to implement type-transforming middleware, as well as a way to easily implement stubbing.

Installation

From the command line:

$ cabal install request-monad

To use data types and functions export from this library:

import Control.Monad.Request

Usage

Using RequestT r r' m a abstracts sending requests of type r, and handling responses of r'. Below is an example of using RequestT to ask for somebody's name and age. Note that there is no logic about how to get and return the strings in getNameAndAge, that's all handled in prompt.

import Control.Monad
import Control.Monad.Request
import System.IO

getNameAndAge :: Monad m => RequestT String String m (String, Int)
getNameAndAge = do
    name <- send "Name: "
    age <- liftM read $ send "Age: "
    return (name, age)

prompt :: String -> IO String
prompt str = putStr str >> hFlush stdout >> getLine

main :: IO ()
main = do
    (name, age) <- runRequestT getNameAndAge prompt
    putStrLn $ name ++ " is " ++ show age ++ " years old."

Below is an example of an echo server, which just returns the exact input that it was given.

import Control.Monad.Request

pingPong :: Monad m => RequestT String String m (String, String)
pingPong = do
    a <- send "ping"
    b <- send "pong"
    return (a, b)

main :: IO ()
main = do
    let (a, b) = runRequest pingPong id
    putStrLn $ "a: " ++ a -- Prints "a: ping"
    putStrLn $ "b: " ++ b -- Prints "b: pong"

Aside from implementation-independant requests, this abstraction also simplifies adding request/response middleware. The code below adds JSON deserialization to each response.

{-# LANGUAGE OverloadedStrings #-}

import Control.Monad
import Control.Monad.Request
import qualified Data.Aeson as A
import qualified Data.ByteString.Lazy as B

deserialize :: (A.FromJSON a, Monad m) => B.ByteString -> m (Maybe a)
deserialize = return . A.decode

tryTwice :: Monad m => RequestT B.ByteString B.ByteString m (Maybe A.Value)
tryTwice = mapResponseT deserialize $ do
    a <- send "request one"
    b <- send "request two"
    return $ a `mplus` b

handleRequest :: Monad m => B.ByteString -> B.ByteString
handleRequest "request one" = return "not json"
handleRequest x             = "[15]"

main :: IO ()
main = do
    let res = runRequest tryTwice handleRequest
    print $ res -- Prints "Just (Array (fromList [Number 15.0]))"

TODO

  • Add a strict version of RequestT.
Metadata

Version

0.3.0.1

License

Platforms (75)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-darwin
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-darwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-windows