{-# OPTIONS_GHC -fno-warn-redundant-constraints #-} {-# LANGUAGE Arrows, CPP, TypeOperators #-} -- Test infix type notation and arrow notation module Test where import Prelude hiding (id,(.)) import Control.Category import Control.Arrow -- For readability, I use infix notation for arrow types. I'd prefer the -- following, but GHC doesn't allow operators like "-=>" as type -- variables. -- -- comp1 :: Arrow (-=>) => b-=>c -> c-=>d -> b-=>d comp1 :: Arrow to => b `to` c -> c `to` d -> b `to` d comp1 f g = proc x -> do b <- f -< x g -< b -- arrowp produces -- comp1 f g = (f >>> g) comp :: Arrow to => (b `to` c, c `to` d) `to` (b `to` d) comp = arr (uncurry (>>>)) -- app :: Arrow to => (b c, b) `to` c type R = Float type I = Int z1,z2 :: Arrow to => I `to` (R `to` R) z1 = undefined z2 = z1 z3 :: Arrow to => (I,I) `to` (R `to` R,R `to` R) z3 = z1 *** z2 z4 :: Arrow to => (I,I) `to` (R `to` R) z4 = z3 >>> comp comp4,comp5 :: Arrow to => b `to` (c `to` d) -> e `to` (d `to` f) -> (b,e) `to` (c `to` f) comp4 g f = proc (b,e) -> do g' <- g -< b f' <- f -< e returnA -< (g' >>> f') comp5 g f = (g *** f) >>> comp lam,lam2 :: Arrow to => (e,b) `to` c -> e `to` (b `to` c) lam f = arr $ \ e -> arr (pair e) >>> f pair a b = (a,b) -- I got the definition lam above by starting with lam2 f = proc e -> returnA -< (proc b -> do c <- f -< (e,b) returnA -< c) -- I desugared with the arrows preprocessor, removed extra parens and -- renamed "arr" to "pure", to get -- -- lam f = pure (\ e -> pure (\ b -> (e, b)) >>> f) -- Note that lam is arrow curry -- curry :: ((e,b) -> c) -> (e -> b -> c) -- All equivalent: curry1 f e b = f (e,b) curry2 f = \ e -> \ b -> f (e,b) curry3 f = \ e -> f . (\ b -> (e,b)) curry4 f = \ e -> f . (pair e) comp6 :: Arrow to => b `to` (c `to` d) -> e `to` (d `to` f) -> b `to` (e `to` (c `to` f)) comp6 g f = lam $ comp5 g f -- What about uncurrying? -- uncurryA :: Arrow to => b `to` (c `to` d) -- -> (b,c) `to` d -- uncurryA f = proc (b,c) -> do -- f' <- f -< b -- returnA -< f' c -- Why "lam" instead of "curryA" (good name also): so I can use Arrows -- lambda notation, similar to compF g f = \ b e -> g b . f e -- But I haven't figured out how to. -- comp7 :: Arrow to => b `to` (c `to` d) -> e `to` (d `to` f) -- -> b `to` (e `to` (c `to` f)) -- comp7 g f = proc b -> proc e -> do -- g' <- g -< b -- f' <- f -< e -- returnA -< (g' >>> f') -- Try "(| lam \ b -> ... |)" in the FOP arrows chapter -- cmd ::= form exp cmd1 ... cmdn. Parens if nec -- (| lam (\ b -> undefined) |) -- Oh! The arrow syntax allows bindings with *infix* operators. And I -- don't know how to finish comp7. -- Uncurried forms: comp8 :: Arrow to => (b,c) `to` d -> (e,d) `to` k -> (b,c,e) `to` k comp8 g f = proc (b,c,e) -> do d <- g -< (b,c) f -< (e,d) -- This looks like straightforward `to` translation. With insertions of -- curry & uncurry operators, it'd probably be easy to handle curried -- definitions as well. -- Simpler example, for experimentation comp9 :: Arrow to => (c,d) `to` e -> b `to` d -> (b,c) `to` e comp9 g f = proc (b,c) -> do d <- f -< b g -< (c,d) -- Desugared: comp9' :: Arrow to => (c,d) `to` e -> b `to` d -> (b,c) `to` e comp9' g f = first f >>> arr (\ (d,c) -> (c,d)) >>> g