{- Following a suggestion by oleg@okmij.org, 2010-08-06 -} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE OverlappingInstances #-} module Control.Arrow.Let where import Control.Arrow (Arrow, arr, (&&&), (<<<), (^<<), (^>>), (>>^), ) class Index t envi envo where ref :: Arrow arr => arr envi t -> arr envo t instance Index t envi (t,envi) where ref _ = arr fst instance Index t envi envo => Index t envi (h,envo) where ref (ai :: arr envi t) = snd ^>> (ref ai :: arr envo t) infixl 1 <<<& (<<<&) :: Arrow arrow => arrow (b,a) c -> arrow a b -> arrow a c x <<<& y = x <<< y &&& arr id input :: Arrow arrow => arrow () Int f :: Arrow arrow => arrow (Int,()) Char g :: Arrow arrow => arrow (Char,(Int,())) Bool input = undefined f = undefined g = undefined c1 :: Arrow arrow => arrow (Int,()) Bool c1 = let inp1 = ref input >>^ ( > 1) inp2 = ref f >>^ ( == 'a') in (uncurry (&&) ^<< inp1 &&& inp2) <<<& f c2 :: Arrow arrow => arrow (Int,()) Bool c2 = let inp1 = ref input >>^ ( > 1) inp2 = ref f >>^ (== 'a') h = uncurry (||) ^<< ref g &&& (uncurry (&&) ^<< inp1 &&& inp2) in h <<<& g <<<& f