arrowp-qq-0.3.0: examples/cgi/ArrowContext.lhs
> {-# LANGUAGE DatatypeContexts #-}
> {-# LANGUAGE FlexibleContexts #-}
> {-# LANGUAGE FlexibleInstances #-}
> {-# LANGUAGE MultiParamTypeClasses #-}
> {-# OPTIONS -F -pgmF arrowp-ext #-}
Basic definitions from "Generalising Monads to Arrows", by John Hughes,
but with the Arrow class split and generalized.
> module ArrowContext where
> import Control.Monad
> infixr 5 <+>
> infixr 3 ***
> infixr 3 &&&
> infixr 2 +++
> infixr 2 |||
> infixr 1 >>>
Basic arrow definitions (s4.1)
> class Arrow a where
> arr :: (b -> c) -> a b c
> (>>>) :: a b c -> a c d -> a b d
> class Arrow a => ArrowContext a d where
> first :: a b c -> a (b,d) (c,d)
> newtype Kleisli m a b = Kleisli (a -> m b)
> instance Monad m => Arrow (Kleisli m) where
> arr f = Kleisli (return . f)
> (Kleisli f) >>> (Kleisli g) = Kleisli (\b -> f b >>= g)
> instance Monad m => ArrowContext (Kleisli m) d where
> first (Kleisli f) = Kleisli (\(b,d) -> f b >>= \c -> return (c,d))
> second :: ArrowContext a d => a b c -> a (d,b) (d,c)
> second f = arr swap >>> first f >>> arr swap
> where swap ~(x,y) = (y,x)
> (***) :: (ArrowContext a b', ArrowContext a c) =>
> a b c -> a b' c' -> a (b,b') (c,c')
> f *** g = first f >>> second g
> (&&&) :: (ArrowContext a b, ArrowContext a c) =>
> a b c -> a b c' -> a b (c,c')
> f &&& g = arr (\b -> (b,b)) >>> f *** g
> liftA2 :: (ArrowContext a b, ArrowContext a e) =>
> (b -> c -> d) -> a e b -> a e c -> a e d
> liftA2 op f g = f &&& g >>> arr (uncurry op)
ArrowPlus and ArrowZero (s4.2)
> class Arrow a => ArrowZero a where
> zeroArrow :: a b c
> class ArrowZero a => ArrowPlus a where
> (<+>) :: a b c -> a b c -> a b c
> instance MonadPlus m => ArrowZero (Kleisli m) where
> zeroArrow = Kleisli (\x -> mzero)
> instance MonadPlus m => ArrowPlus (Kleisli m) where
> Kleisli f <+> Kleisli g = Kleisli (\x -> f x `mplus` g x)
Conditionals (s5.1)
> class Arrow a => ArrowChoice a where
> left :: a b c -> a (Either b d) (Either c d)
> instance Monad m => ArrowChoice (Kleisli m) where
> left (Kleisli f) = Kleisli g
> where g (Left b) = f b >>= (return . Left)
> g (Right d) = return (Right d)
> right :: ArrowChoice a => a b c -> a (Either d b) (Either d c)
> right f = arr mirror >>> left f >>> arr mirror
> where mirror (Left x) = Right x
> mirror (Right y) = Left y
> (+++) :: ArrowChoice a => a b c -> a b' c' -> a (Either b b') (Either c c')
> f +++ g = left f >>> right g
> (|||) :: ArrowChoice a => a b d -> a c d -> a (Either b c) d
> f ||| g = f +++ g >>> arr untag
> where untag (Left x) = x
> untag (Right y) = y
> test :: (ArrowContext a Bool, ArrowContext a b) =>
> a b Bool -> a b (Either b b)
> test f = f &&& arr id >>> arr (\(b, x) -> if b then Left x else Right x)
Application (s5.2)
> class Arrow a => ArrowApply a where
> app :: a (a b c, b) c
> leftApp :: ArrowApply a => a b c -> a (Either b d) (Either c d)
> leftApp f = arr ((\b -> (arr (\() -> b) >>> f >>> arr Left, ())) |||
> (\d -> (arr (\() -> d) >>> arr Right, ()))) >>> app
> instance Monad m => ArrowApply (Kleisli m) where
> app = Kleisli (\(Kleisli f, x) -> f x)
> newtype ArrowApply a => ArrowMonad a b = ArrowMonad (a () b)
> instance ArrowApply a => Functor (ArrowMonad a) where
> fmap = liftM
> instance ArrowApply a => Applicative (ArrowMonad a) where
> pure = return
> (<*>) = ap
> instance ArrowApply a => Monad (ArrowMonad a) where
> return x = ArrowMonad (arr (\z -> x))
> ArrowMonad m >>= f = ArrowMonad (m >>>
> arr (\x -> let ArrowMonad h = f x in (h, ())) >>>
> app)
The ordinary function type (s7)
> instance Arrow (->) where
> arr f = f
> f >>> g = g . f
> instance ArrowContext (->) a where
> first f (x,y) = (f x, y)
> instance ArrowChoice (->) where
> left f (Left x) = Left (f x)
> left f (Right y) = Right y
> instance ArrowApply (->) where
> app (f,x) = f x
Auxiliary functions used in stating laws (s7)
> assoc :: ((a,b),c) -> (a,(b,c))
> assoc ~(~(x,y),z) = (x,(y,z))
> assocsum :: Either (Either a b) c -> Either a (Either b c)
> assocsum (Left (Left x)) = Left x
> assocsum (Left (Right y)) = Right (Left y)
> assocsum (Right z) = Right (Right z)
Another definition used by the arrow notation.
> returnA :: Arrow a => a b b
> returnA = arr id