-- | -- Module : Data.OI.Combinator -- Copyright : (c) Nobuo Yamashita 2011-2016 -- License : BSD3 -- Author : Nobuo Yamashita -- Maintainer : nobsun@sampou.org -- Stability : experimental -- {-# LANGUAGE TypeOperators #-} module Data.OI.Combinator ( -- * Interaction Combinators (|:|) ,(|>|),(|/|) ,(|><|) -- * Iteration ,sequenceOI ,foldOI ,mapOI ,zipWithOI ,zipWithOI' -- * Conditional Choice ,ifOI ,choiceOI ,choiceOIOn -- * Sequencing ,seqsOI ,seqsOI' ) where import Data.OI.Internal import Data.OI.Force -- | Connect two interactions into an interaction infixl 3 |:| infixl 2 |>|,|/| infixl 1 |><| (|:|) :: (a :-> c) -> (b :-> d) -> ((a,b) :-> (c,d)) (f |:| g) o = case dePair o of (a,b) -> (f a, g b) (|/|) :: (a :-> c) -> (c -> (b :-> d)) -> ((a,b) :-> d) (f |/| g) o = case dePair o of (a,b) -> g (f a) b (|>|) :: (a :-> (p,c)) -> (b :-> (p -> d)) -> ((a,b) :-> (c,d)) (f |>| g) o = case dePair o of (a,b) -> (c, g b p) where (p,c) = f a (|><|) :: (a :-> (p -> (q,c))) -> (b :-> (q -> (p,d))) -> ((a,b) :-> (c,d)) (f |><| g) o = case dePair o of (a,b) -> (c,d) where (q,c) = f a p; (p,d) = g b q -- | Iteration foldOI :: (a :-> (b -> b)) -> b -> ([a] :-> b) foldOI op z xxs = case deList xxs of Just (x,xs) -> x `op` foldOI op z xs _ -> z sequenceOI :: [a :-> b] -> [a] :-> [b] sequenceOI (f:fs) oos = case deList oos of Just (o,os) -> f o : sequenceOI fs os _ -> [] sequenceOI _ _ = [] mapOI :: (a :-> b) -> ([a] :-> [b]) mapOI f = sequenceOI (repeat f) zipWithOI :: (a -> (b :-> c)) -> ([a] -> ([b] :-> [c])) zipWithOI _ [] _ = [] zipWithOI f (b:bs) os = case deList os of Just (x,xs) -> f b x : zipWithOI f bs xs _ -> [] zipWithOI' :: (a :-> (b -> c)) -> ([a] :-> ([b] -> [c])) zipWithOI' = flip . zipWithOI . flip -- | Conditional branching ifOI :: Bool -> (a :-> c) -> (b :-> c) -> (Either a b :-> c) ifOI True t _ o = case deLeft o of Left x -> t x _ -> error "ifOI: Left expected but Right" ifOI False _ e o = case deRight o of Right y -> e y _ -> error "ifOI: Right expected but Left" choiceOI :: (a :-> c) -> (b :-> c) -> Bool -> (Either a b :-> c) choiceOI = flip . flip ifOI choiceOIOn :: (t -> a :-> c) -> (t -> b :-> c) -> (t -> Bool) -> t -> Either a b :-> c choiceOIOn f g p x = choiceOI (f x) (g x) (p x) -- | Sequencing seqsOI :: [a :-> b] -> ([a] :-> ()) seqsOI s os = forceSeq $ zipWithOI ($) s os seqsOI' :: [a] :-> ([a :-> b] -> ()) seqsOI' os is = case dropWhile (()==) $ map force $ zipWithOI id is os of [] -> () _ -> error "seqsOI': Impossible!"