{-# LANGUAGE ExistentialQuantification, PatternGuards, Rank2Types #-}

-- | This marvellous module contributed by Thomas J\344ger
module Lambdabot.Plugin.Haskell.Pl.Rules (RewriteRule(..), fire, rules) where

import Lambdabot.Plugin.Haskell.Pl.Common
import Lambdabot.Plugin.Haskell.Pl.RuleLib
import Lambdabot.Plugin.Haskell.Pl.Names


----------------------------------------------------------------------------------------
-- Operator rules

collapseLists :: Expr -> Maybe Expr
collapseLists :: Expr -> Maybe Expr
collapseLists (Var Fixity
_ [Char]
"++" `App` Expr
e1 `App` Expr
e2)
  | ([Expr]
xs,Expr
x) <- Expr -> ([Expr], Expr)
getList Expr
e1, Expr
xExpr -> Expr -> Bool
forall a. Eq a => a -> a -> Bool
==Expr
nil,
    ([Expr]
ys,Expr
y) <- Expr -> ([Expr], Expr)
getList Expr
e2, Expr
yExpr -> Expr -> Bool
forall a. Eq a => a -> a -> Bool
==Expr
nil = Expr -> Maybe Expr
forall a. a -> Maybe a
Just (Expr -> Maybe Expr) -> Expr -> Maybe Expr
forall a b. (a -> b) -> a -> b
$ [Expr] -> Expr
makeList ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ [Expr]
xs [Expr] -> [Expr] -> [Expr]
forall a. [a] -> [a] -> [a]
++ [Expr]
ys
collapseLists Expr
_ = Maybe Expr
forall a. Maybe a
Nothing

data Binary = forall a b c. (Read a, Show a, Read b, Show b, Read c, Show c) => BA (a -> b -> c)

evalBinary :: [(String, Binary)] -> Expr -> Maybe Expr
evalBinary :: [([Char], Binary)] -> Expr -> Maybe Expr
evalBinary [([Char], Binary)]
fs (Var Fixity
_ [Char]
f' `App` Var Fixity
_ [Char]
x' `App` Var Fixity
_ [Char]
y')
  | Just (BA a -> b -> c
f) <- [Char] -> [([Char], Binary)] -> Maybe Binary
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup [Char]
f' [([Char], Binary)]
fs = (Fixity -> [Char] -> Expr
Var Fixity
Pref ([Char] -> Expr) -> (c -> [Char]) -> c -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. c -> [Char]
forall a. Show a => a -> [Char]
show) (c -> Expr) -> Maybe c -> Maybe Expr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` (a -> b -> c) -> Maybe a -> Maybe b -> Maybe c
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 a -> b -> c
f ([Char] -> Maybe a
forall a (m :: * -> *). (Read a, Alternative m) => [Char] -> m a
readM [Char]
x') ([Char] -> Maybe b
forall a (m :: * -> *). (Read a, Alternative m) => [Char] -> m a
readM [Char]
y')
evalBinary [([Char], Binary)]
_ Expr
_ = Maybe Expr
forall a. Maybe a
Nothing

data Unary = forall a b. (Read a, Show a, Read b, Show b) => UA (a -> b)

evalUnary :: [(String, Unary)] -> Expr -> Maybe Expr
evalUnary :: [([Char], Unary)] -> Expr -> Maybe Expr
evalUnary [([Char], Unary)]
fs (Var Fixity
_ [Char]
f' `App` Var Fixity
_ [Char]
x')
  | Just (UA a -> b
f) <- [Char] -> [([Char], Unary)] -> Maybe Unary
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup [Char]
f' [([Char], Unary)]
fs = (Fixity -> [Char] -> Expr
Var Fixity
Pref ([Char] -> Expr) -> (a -> [Char]) -> a -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> [Char]
forall a. Show a => a -> [Char]
show (b -> [Char]) -> (a -> b) -> a -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f) (a -> Expr) -> Maybe a -> Maybe Expr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` [Char] -> Maybe a
forall a (m :: * -> *). (Read a, Alternative m) => [Char] -> m a
readM [Char]
x'
evalUnary [([Char], Unary)]
_ Expr
_ = Maybe Expr
forall a. Maybe a
Nothing

assocR, assocL, assoc :: [String] -> Expr -> Maybe Expr
-- (f `op` g) `op` h --> f `op` (g `op` h)
assocR :: [[Char]] -> Expr -> Maybe Expr
assocR [[Char]]
ops (Var Fixity
f1 [Char]
op1 `App` (Var Fixity
f2 [Char]
op2 `App` Expr
e1 `App` Expr
e2) `App` Expr
e3)
  | [Char]
op1 [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
op2 Bool -> Bool -> Bool
&& [Char]
op1 [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]]
ops
  = Expr -> Maybe Expr
forall a. a -> Maybe a
Just (Fixity -> [Char] -> Expr
Var Fixity
f1 [Char]
op1 Expr -> Expr -> Expr
`App` Expr
e1 Expr -> Expr -> Expr
`App` (Fixity -> [Char] -> Expr
Var Fixity
f2 [Char]
op2 Expr -> Expr -> Expr
`App` Expr
e2 Expr -> Expr -> Expr
`App` Expr
e3))
assocR [[Char]]
_ Expr
_ = Maybe Expr
forall a. Maybe a
Nothing

-- f `op` (g `op` h) --> (f `op` g) `op` h
assocL :: [[Char]] -> Expr -> Maybe Expr
assocL [[Char]]
ops (Var Fixity
f1 [Char]
op1 `App` Expr
e1 `App` (Var Fixity
f2 [Char]
op2 `App` Expr
e2 `App` Expr
e3))
  | [Char]
op1 [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
op2 Bool -> Bool -> Bool
&& [Char]
op1 [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]]
ops
  = Expr -> Maybe Expr
forall a. a -> Maybe a
Just (Fixity -> [Char] -> Expr
Var Fixity
f1 [Char]
op1 Expr -> Expr -> Expr
`App` (Fixity -> [Char] -> Expr
Var Fixity
f2 [Char]
op2 Expr -> Expr -> Expr
`App` Expr
e1 Expr -> Expr -> Expr
`App` Expr
e2) Expr -> Expr -> Expr
`App` Expr
e3)
assocL [[Char]]
_ Expr
_ = Maybe Expr
forall a. Maybe a
Nothing

-- op f . op g --> op (f `op` g)
assoc :: [[Char]] -> Expr -> Maybe Expr
assoc [[Char]]
ops (Var Fixity
_ [Char]
"." `App` (Var Fixity
f1 [Char]
op1 `App` Expr
e1) `App` (Var Fixity
f2 [Char]
op2 `App` Expr
e2))
  | [Char]
op1 [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
op2 Bool -> Bool -> Bool
&& [Char]
op1 [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]]
ops
  = Expr -> Maybe Expr
forall a. a -> Maybe a
Just (Fixity -> [Char] -> Expr
Var Fixity
f1 [Char]
op1 Expr -> Expr -> Expr
`App` (Fixity -> [Char] -> Expr
Var Fixity
f2 [Char]
op2 Expr -> Expr -> Expr
`App` Expr
e1 Expr -> Expr -> Expr
`App` Expr
e2))
assoc [[Char]]
_ Expr
_ = Maybe Expr
forall a. Maybe a
Nothing

commutative :: [String] -> Expr -> Maybe Expr
commutative :: [[Char]] -> Expr -> Maybe Expr
commutative [[Char]]
ops (Var Fixity
f [Char]
op `App` Expr
e1 `App` Expr
e2)
  | [Char]
op [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]]
ops = Expr -> Maybe Expr
forall a. a -> Maybe a
Just (Fixity -> [Char] -> Expr
Var Fixity
f [Char]
op Expr -> Expr -> Expr
`App` Expr
e2 Expr -> Expr -> Expr
`App` Expr
e1)
commutative [[Char]]
ops (Var Fixity
_ [Char]
"flip" `App` e :: Expr
e@(Var Fixity
_ [Char]
op)) | [Char]
op [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]]
ops = Expr -> Maybe Expr
forall a. a -> Maybe a
Just Expr
e
commutative [[Char]]
_ Expr
_ = Maybe Expr
forall a. Maybe a
Nothing

----------------------------------------------------------------------------------------
-- Rewrite rules


-- TODO: Move rules into a file.
{-# INLINE simplifies #-}
simplifies :: RewriteRule
simplifies :: RewriteRule
simplifies = [RewriteRule] -> RewriteRule
Or [
  -- (f . g) x --> f (g x)
  (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f MExpr
g MExpr
x -> (MExpr
f MExpr -> MExpr -> MExpr
`c` MExpr
g) MExpr -> MExpr -> MExpr
`a` MExpr
x)
      (\MExpr
f MExpr
g MExpr
x -> MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
g MExpr -> MExpr -> MExpr
`a` MExpr
x)),
  -- id x --> x
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
x -> MExpr
idE MExpr -> MExpr -> MExpr
`a` MExpr
x)
      (\MExpr
x -> MExpr
x),
  -- flip (flip x) --> x
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x -> MExpr
flipE MExpr -> MExpr -> MExpr
`a` (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
x))
      (\MExpr
x -> MExpr
x),
  -- flip id x . f --> flip f x
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f MExpr
x -> (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
idE MExpr -> MExpr -> MExpr
`a` MExpr
x) MExpr -> MExpr -> MExpr
`c` MExpr
f)
      (\MExpr
f MExpr
x -> MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x),
  -- id . f --> f
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f -> MExpr
idE MExpr -> MExpr -> MExpr
`c` MExpr
f)
      (\MExpr
f -> MExpr
f),
  -- f . id --> f
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f -> MExpr
f MExpr -> MExpr -> MExpr
`c` MExpr
idE)
      (\MExpr
f -> MExpr
f),
  -- const x y --> x
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
x MExpr
y -> MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y)
      (\MExpr
x MExpr
_ -> MExpr
x),
  -- not (not x) --> x
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x -> MExpr
notE MExpr -> MExpr -> MExpr
`a` (MExpr
notE MExpr -> MExpr -> MExpr
`a` MExpr
x))
      (\MExpr
x -> MExpr
x),
  -- fst (x,y) --> x
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x MExpr
y -> MExpr
fstE MExpr -> MExpr -> MExpr
`a` (MExpr
commaE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y))
      (\MExpr
x MExpr
_ -> MExpr
x),
  -- snd (x,y) --> y
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x MExpr
y -> MExpr
sndE MExpr -> MExpr -> MExpr
`a` (MExpr
commaE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y))
      (\MExpr
_ MExpr
y -> MExpr
y),
  -- head (x:xs) --> x
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x MExpr
xs -> MExpr
headE MExpr -> MExpr -> MExpr
`a` (MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
xs))
      (\MExpr
x MExpr
_  -> MExpr
x),
  -- tail (x:xs) --> xs
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x MExpr
xs -> MExpr
tailE MExpr -> MExpr -> MExpr
`a` (MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
xs))
      (\MExpr
_ MExpr
xs -> MExpr
xs),
  -- uncurry f (x,y) --> f x y
  (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr1 (\MExpr
f MExpr
x MExpr
y -> MExpr
uncurryE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
commaE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y))
      (\MExpr
f MExpr
x MExpr
y -> MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y),
  -- uncurry (,) --> id
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (MExpr
uncurryE MExpr -> MExpr -> MExpr
`a` MExpr
commaE)
      (MExpr
idE),
  -- uncurry f . s (,) g --> s f g
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr1 (\MExpr
f MExpr
g -> (MExpr
uncurryE MExpr -> MExpr -> MExpr
`a` MExpr
f) MExpr -> MExpr -> MExpr
`c` (MExpr
sE MExpr -> MExpr -> MExpr
`a` MExpr
commaE MExpr -> MExpr -> MExpr
`a` MExpr
g))
      (\MExpr
f MExpr
g -> MExpr
sE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
g),
  -- curry fst --> const
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (MExpr
curryE MExpr -> MExpr -> MExpr
`a` MExpr
fstE) (MExpr
constE),
  -- curry snd --> const id
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (MExpr
curryE MExpr -> MExpr -> MExpr
`a` MExpr
sndE) (MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
idE),
  -- s f g x --> f x (g x)
  (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f MExpr
g MExpr
x -> MExpr
sE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
g MExpr -> MExpr -> MExpr
`a` MExpr
x)
      (\MExpr
f MExpr
g MExpr
x -> MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` (MExpr
g MExpr -> MExpr -> MExpr
`a` MExpr
x)),
  -- flip f x y --> f y x
  (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f MExpr
x MExpr
y -> MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y)
      (\MExpr
f MExpr
x MExpr
y -> MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
y MExpr -> MExpr -> MExpr
`a` MExpr
x),
  -- flip (=<<) --> (>>=)
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
extE)
      MExpr
bindE,

  -- TODO: Think about map/fmap
  -- fmap id --> id
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (MExpr
fmapE MExpr -> MExpr -> MExpr
`a` MExpr
idE)
     (MExpr
idE),
  -- map id --> id
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (MExpr
mapE MExpr -> MExpr -> MExpr
`a` MExpr
idE)
     (MExpr
idE),
  -- (f . g) . h --> f . (g . h)
  (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f MExpr
g MExpr
h -> (MExpr
f MExpr -> MExpr -> MExpr
`c` MExpr
g) MExpr -> MExpr -> MExpr
`c` MExpr
h)
      (\MExpr
f MExpr
g MExpr
h -> MExpr
f MExpr -> MExpr -> MExpr
`c` (MExpr
g MExpr -> MExpr -> MExpr
`c` MExpr
h)),
  -- fmap f . fmap g -> fmap (f . g)
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f MExpr
g -> MExpr
fmapE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`c` MExpr
fmapE MExpr -> MExpr -> MExpr
`a` MExpr
g)
      (\MExpr
f MExpr
g -> MExpr
fmapE MExpr -> MExpr -> MExpr
`a` (MExpr
f MExpr -> MExpr -> MExpr
`c` MExpr
g)),
  -- map f . map g -> map (f . g)
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f MExpr
g -> MExpr
mapE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`c` MExpr
mapE MExpr -> MExpr -> MExpr
`a` MExpr
g)
      (\MExpr
f MExpr
g -> MExpr
mapE MExpr -> MExpr -> MExpr
`a` (MExpr
f MExpr -> MExpr -> MExpr
`c` MExpr
g))

  ]

onceRewrites :: RewriteRule
onceRewrites :: RewriteRule
onceRewrites = RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ [RewriteRule] -> RewriteRule
Or [
  -- ($) --> id
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (MExpr
dollarE)
      MExpr
idE,
  -- concatMap --> (=<<)
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr MExpr
concatMapE MExpr
extE,
  -- concat    --> join
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr MExpr
concatE MExpr
joinE,
  -- liftM --> fmap
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr MExpr
liftME MExpr
fmapE,
  -- map --> fmap
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr MExpr
mapE MExpr
fmapE,
  -- subtract -> flip (-)
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  MExpr
subtractE
      (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
minusE)
  ]

-- Now we can state rewrite rules in a nice high level way
-- Rewrite rules should be as pointful as possible since the pointless variants
-- will be derived automatically.
rules :: RewriteRule
rules :: RewriteRule
rules = [RewriteRule] -> RewriteRule
Or [
  -- f (g x) --> (f . g) x
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
f MExpr
g MExpr
x -> MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
g MExpr -> MExpr -> MExpr
`a` MExpr
x))
      (\MExpr
f MExpr
g MExpr
x -> (MExpr
f MExpr -> MExpr -> MExpr
`c` MExpr
g) MExpr -> MExpr -> MExpr
`a` MExpr
x),
  -- (>>=) --> flip (=<<)
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  MExpr
bindE
      (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
extE),
  -- (.) id --> id
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (MExpr
compE MExpr -> MExpr -> MExpr
`a` MExpr
idE)
     MExpr
idE,
  -- (++) [x] --> (:) x
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x -> MExpr
appendE MExpr -> MExpr -> MExpr
`a` (MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
nilE))
      (\MExpr
x -> MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x),
  -- (=<<) return --> id
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (MExpr
extE MExpr -> MExpr -> MExpr
`a` MExpr
returnE)
      MExpr
idE,
  -- (=<<) f (return x) -> f x
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
f MExpr
x -> MExpr
extE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
returnE MExpr -> MExpr -> MExpr
`a` MExpr
x))
      (\MExpr
f MExpr
x -> MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x),
  -- (=<<) ((=<<) f . g) --> (=<<) f . (=<<) g
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
f MExpr
g -> MExpr
extE MExpr -> MExpr -> MExpr
`a` ((MExpr
extE MExpr -> MExpr -> MExpr
`a` MExpr
f) MExpr -> MExpr -> MExpr
`c` MExpr
g))
      (\MExpr
f MExpr
g -> (MExpr
extE MExpr -> MExpr -> MExpr
`a` MExpr
f) MExpr -> MExpr -> MExpr
`c` (MExpr
extE MExpr -> MExpr -> MExpr
`a` MExpr
g)),
  -- flip (f . g) --> flip (.) g . flip f
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
f MExpr
g -> MExpr
flipE MExpr -> MExpr -> MExpr
`a` (MExpr
f MExpr -> MExpr -> MExpr
`c` MExpr
g))
      (\MExpr
f MExpr
g -> (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
compE MExpr -> MExpr -> MExpr
`a` MExpr
g) MExpr -> MExpr -> MExpr
`c` (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
f)),
  -- flip (.) f . flip id --> flip f
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
f -> (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
compE MExpr -> MExpr -> MExpr
`a` MExpr
f) MExpr -> MExpr -> MExpr
`c` (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
idE))
      (\MExpr
f -> MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
f),
  -- flip (.) f . flip flip --> flip (flip . f)
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
f -> (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
compE MExpr -> MExpr -> MExpr
`a` MExpr
f) MExpr -> MExpr -> MExpr
`c` (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
flipE))
      (\MExpr
f -> MExpr
flipE MExpr -> MExpr -> MExpr
`a` (MExpr
flipE MExpr -> MExpr -> MExpr
`c` MExpr
f)),
  -- flip (flip (flip . f) g) --> flip (flip . flip f) g
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr1 (\MExpr
f MExpr
g -> MExpr
flipE MExpr -> MExpr -> MExpr
`a` (MExpr
flipE MExpr -> MExpr -> MExpr
`a` (MExpr
flipE MExpr -> MExpr -> MExpr
`c` MExpr
f) MExpr -> MExpr -> MExpr
`a` MExpr
g))
      (\MExpr
f MExpr
g -> MExpr
flipE MExpr -> MExpr -> MExpr
`a` (MExpr
flipE MExpr -> MExpr -> MExpr
`c` MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
f) MExpr -> MExpr -> MExpr
`a` MExpr
g),

  -- flip (.) id --> id
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
compE MExpr -> MExpr -> MExpr
`a` MExpr
idE)
     MExpr
idE,
  -- (.) . flip id --> flip flip
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (MExpr
compE MExpr -> MExpr -> MExpr
`c` (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
idE))
      (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
flipE),
  -- s const x y --> y
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x MExpr
y -> MExpr
sE MExpr -> MExpr -> MExpr
`a` MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y)
      (\MExpr
_ MExpr
y -> MExpr
y),
  -- s (const . f) g --> f
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr1 (\MExpr
f MExpr
g -> MExpr
sE MExpr -> MExpr -> MExpr
`a` (MExpr
constE MExpr -> MExpr -> MExpr
`c` MExpr
f) MExpr -> MExpr -> MExpr
`a` MExpr
g)
      (\MExpr
f MExpr
_ -> MExpr
f),
  -- s (const f) --> (.) f
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
f -> MExpr
sE MExpr -> MExpr -> MExpr
`a` (MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
f))
      (\MExpr
f -> MExpr
compE MExpr -> MExpr -> MExpr
`a` MExpr
f),
  -- (`ap` f) . const . h --> (. f) . h
  (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
f MExpr
g MExpr
h -> (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
sE MExpr -> MExpr -> MExpr
`a` MExpr
f) MExpr -> MExpr -> MExpr
`c` (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
compE MExpr -> MExpr -> MExpr
`a` MExpr
g) MExpr -> MExpr -> MExpr
`c` MExpr
constE MExpr -> MExpr -> MExpr
`c` MExpr
h)
      (\MExpr
f MExpr
_ MExpr
h -> (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
compE MExpr -> MExpr -> MExpr
`a` MExpr
f) MExpr -> MExpr -> MExpr
`c` MExpr
h),
  -- s (f . fst) snd --> uncurry f
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
f -> MExpr
sE MExpr -> MExpr -> MExpr
`a` (MExpr
f MExpr -> MExpr -> MExpr
`c` MExpr
fstE) MExpr -> MExpr -> MExpr
`a` MExpr
sndE)
      (\MExpr
f -> MExpr
uncurryE MExpr -> MExpr -> MExpr
`a` MExpr
f),
  -- fst (join (,) x) --> x
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
x -> MExpr
fstE MExpr -> MExpr -> MExpr
`a` (MExpr
joinE MExpr -> MExpr -> MExpr
`a` MExpr
commaE MExpr -> MExpr -> MExpr
`a` MExpr
x))
     (\MExpr
x -> MExpr
x),
  -- snd (join (,) x) --> x
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
x -> MExpr
sndE MExpr -> MExpr -> MExpr
`a` (MExpr
joinE MExpr -> MExpr -> MExpr
`a` MExpr
commaE MExpr -> MExpr -> MExpr
`a` MExpr
x))
     (\MExpr
x -> MExpr
x),
  -- The next two are `simplifies', strictly speaking, but invoked rarely.
  -- uncurry f (x,y) --> f x y
--  rr  (\f x y -> uncurryE `a` f `a` (commaE `a` x `a` y))
--      (\f x y -> f `a` x `a` y),
  -- curry (uncurry f) --> f
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
curryE MExpr -> MExpr -> MExpr
`a` (MExpr
uncurryE MExpr -> MExpr -> MExpr
`a` MExpr
f))
     (\MExpr
f -> MExpr
f),
  -- uncurry (curry f) --> f
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
uncurryE MExpr -> MExpr -> MExpr
`a` (MExpr
curryE MExpr -> MExpr -> MExpr
`a` MExpr
f))
     (\MExpr
f -> MExpr
f),
  -- (const id . f) --> const id
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
f -> (MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
idE) MExpr -> MExpr -> MExpr
`c` MExpr
f)
      (\MExpr
_ -> MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
idE),
  -- const x . f --> const x
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
x MExpr
f -> MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`c` MExpr
f)
     (\MExpr
x MExpr
_ -> MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
x),
  -- (. f) . const --> const
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
compE MExpr -> MExpr -> MExpr
`a` MExpr
f) MExpr -> MExpr -> MExpr
`c` MExpr
constE)
     (\MExpr
_ -> MExpr
constE),
  -- (. f) . const . g --> const . g
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
g -> (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
compE MExpr -> MExpr -> MExpr
`a` MExpr
f) MExpr -> MExpr -> MExpr
`c` MExpr
constE MExpr -> MExpr -> MExpr
`c` MExpr
g)
     (\MExpr
_ MExpr
g -> MExpr
constE MExpr -> MExpr -> MExpr
`c` MExpr
g),
  -- fix f --> f (fix x)
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f -> MExpr
fixE MExpr -> MExpr -> MExpr
`a` MExpr
f)
      (\MExpr
f -> MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
fixE MExpr -> MExpr -> MExpr
`a` MExpr
f)),
  -- f (fix f) --> fix x
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f -> MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
fixE MExpr -> MExpr -> MExpr
`a` MExpr
f))
      (\MExpr
f -> MExpr
fixE MExpr -> MExpr -> MExpr
`a` MExpr
f),
  -- fix f --> f (f (fix x))
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f -> MExpr
fixE MExpr -> MExpr -> MExpr
`a` MExpr
f)
      (\MExpr
f -> MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
fixE MExpr -> MExpr -> MExpr
`a` MExpr
f))),
  -- fix (const f) --> f
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
fixE MExpr -> MExpr -> MExpr
`a` (MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
f))
     (\MExpr
f -> MExpr
f),
  -- flip const x --> id
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x -> MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
x)
      (\MExpr
_ -> MExpr
idE),
  -- const . f --> flip (const f)
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
f -> MExpr
constE MExpr -> MExpr -> MExpr
`c` MExpr
f)
      (\MExpr
f -> MExpr
flipE MExpr -> MExpr -> MExpr
`a` (MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
f)),
  -- not (x == y) -> x /= y
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr2 (\MExpr
x MExpr
y -> MExpr
notE MExpr -> MExpr -> MExpr
`a` (MExpr
equalsE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y))
      (\MExpr
x MExpr
y -> MExpr
nequalsE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y),
  -- not (x /= y) -> x == y
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr2 (\MExpr
x MExpr
y -> MExpr
notE MExpr -> MExpr -> MExpr
`a` (MExpr
nequalsE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y))
      (\MExpr
x MExpr
y -> MExpr
equalsE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y),
  RewriteRule -> RewriteRule -> RewriteRule
If ([RewriteRule] -> RewriteRule
Or [MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr MExpr
plusE MExpr
plusE, MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr MExpr
minusE MExpr
minusE, MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr MExpr
multE MExpr
multE]) (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ RewriteRule -> RewriteRule
down (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ [RewriteRule] -> RewriteRule
Or [
    -- 0 + x --> x
    (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x -> MExpr
plusE MExpr -> MExpr -> MExpr
`a` MExpr
zeroE MExpr -> MExpr -> MExpr
`a` MExpr
x)
        (\MExpr
x -> MExpr
x),
    -- 0 * x --> 0
    (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x -> MExpr
multE MExpr -> MExpr -> MExpr
`a` MExpr
zeroE MExpr -> MExpr -> MExpr
`a` MExpr
x)
        (\MExpr
_ -> MExpr
zeroE),
    -- 1 * x --> x
    (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x -> MExpr
multE MExpr -> MExpr -> MExpr
`a` MExpr
oneE MExpr -> MExpr -> MExpr
`a` MExpr
x)
        (\MExpr
x -> MExpr
x),
    -- x - x --> 0
    (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x -> MExpr
minusE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
x)
        (\MExpr
_ -> MExpr
zeroE),
    -- x - y + y --> x
    (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
y MExpr
x -> MExpr
plusE MExpr -> MExpr -> MExpr
`a` (MExpr
minusE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y) MExpr -> MExpr -> MExpr
`a` MExpr
y)
        (\MExpr
_ MExpr
x -> MExpr
x),
    -- x + y - y --> x
    (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
y MExpr
x -> MExpr
minusE MExpr -> MExpr -> MExpr
`a` (MExpr
plusE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y) MExpr -> MExpr -> MExpr
`a` MExpr
y)
        (\MExpr
_ MExpr
x -> MExpr
x),
    -- x + (y - z) --> x + y - z
    (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x MExpr
y MExpr
z -> MExpr
plusE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` (MExpr
minusE MExpr -> MExpr -> MExpr
`a` MExpr
y MExpr -> MExpr -> MExpr
`a` MExpr
z))
        (\MExpr
x MExpr
y MExpr
z -> MExpr
minusE MExpr -> MExpr -> MExpr
`a` (MExpr
plusE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y) MExpr -> MExpr -> MExpr
`a` MExpr
z),
    -- x - (y + z) --> x - y - z
    (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x MExpr
y MExpr
z -> MExpr
minusE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` (MExpr
plusE MExpr -> MExpr -> MExpr
`a` MExpr
y MExpr -> MExpr -> MExpr
`a` MExpr
z))
        (\MExpr
x MExpr
y MExpr
z -> MExpr
minusE MExpr -> MExpr -> MExpr
`a` (MExpr
minusE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y) MExpr -> MExpr -> MExpr
`a` MExpr
z),
    -- x - (y - z) --> x + y - z
    (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
x MExpr
y MExpr
z -> MExpr
minusE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` (MExpr
minusE MExpr -> MExpr -> MExpr
`a` MExpr
y MExpr -> MExpr -> MExpr
`a` MExpr
z))
        (\MExpr
x MExpr
y MExpr
z -> MExpr
minusE MExpr -> MExpr -> MExpr
`a` (MExpr
plusE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y) MExpr -> MExpr -> MExpr
`a` MExpr
z)
  ],

  RewriteRule -> RewriteRule
Hard RewriteRule
onceRewrites,
  -- join (fmap f x) --> f =<< x
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x -> MExpr
joinE MExpr -> MExpr -> MExpr
`a` (MExpr
fmapE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x))
     (\MExpr
f MExpr
x -> MExpr
extE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x),
  -- (=<<) id --> join
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (MExpr
extE MExpr -> MExpr -> MExpr
`a` MExpr
idE) MExpr
joinE,
  -- join --> (=<<) id
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr MExpr
joinE (MExpr
extE MExpr -> MExpr -> MExpr
`a` MExpr
idE),
  -- join (return x) --> x
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
x -> MExpr
joinE MExpr -> MExpr -> MExpr
`a` (MExpr
returnE MExpr -> MExpr -> MExpr
`a` MExpr
x))
     (\MExpr
x -> MExpr
x),
  -- (return . f) =<< m --> fmap f m
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
m -> MExpr
extE MExpr -> MExpr -> MExpr
`a` (MExpr
returnE MExpr -> MExpr -> MExpr
`c` MExpr
f) MExpr -> MExpr -> MExpr
`a` MExpr
m)
     (\MExpr
f MExpr
m -> MExpr
fmapIE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
m),
  -- (x >>=) . (return .) . f  --> flip (fmap . f) x
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x -> MExpr
bindE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`c` (MExpr
compE MExpr -> MExpr -> MExpr
`a` MExpr
returnE) MExpr -> MExpr -> MExpr
`c` MExpr
f)
     (\MExpr
f MExpr
x -> MExpr
flipE MExpr -> MExpr -> MExpr
`a` (MExpr
fmapIE MExpr -> MExpr -> MExpr
`c` MExpr
f) MExpr -> MExpr -> MExpr
`a` MExpr
x),
  -- (>>=) (return f) --> flip id f
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
bindE MExpr -> MExpr -> MExpr
`a` (MExpr
returnE MExpr -> MExpr -> MExpr
`a` MExpr
f))
     (\MExpr
f -> MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
idE MExpr -> MExpr -> MExpr
`a` MExpr
f),
  -- liftM2 f x --> ap (f `fmap` x)
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x -> MExpr
liftM2E MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x)
     (\MExpr
f MExpr
x -> MExpr
apE MExpr -> MExpr -> MExpr
`a` (MExpr
fmapIE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x)),
  -- liftM2 f (return x) --> fmap (f x)
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x -> MExpr
liftM2E MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
returnE MExpr -> MExpr -> MExpr
`a` MExpr
x))
     (\MExpr
f MExpr
x -> MExpr
fmapIE MExpr -> MExpr -> MExpr
`a` (MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x)),
  -- f `fmap` return x --> return (f x)
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x -> MExpr
fmapE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
returnE MExpr -> MExpr -> MExpr
`a` MExpr
x))
     (\MExpr
f MExpr
x -> MExpr
returnE MExpr -> MExpr -> MExpr
`a` (MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x)),
  -- (=<<) . flip (fmap . f) --> flip liftM2 f
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
extE MExpr -> MExpr -> MExpr
`c` MExpr
flipE MExpr -> MExpr -> MExpr
`a` (MExpr
fmapE MExpr -> MExpr -> MExpr
`c` MExpr
f))
     (\MExpr
f -> MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
liftM2E MExpr -> MExpr -> MExpr
`a` MExpr
f),

  -- (.) -> fmap
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr MExpr
compE MExpr
fmapE,

  -- map f (zip xs ys) --> zipWith (curry f) xs ys
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
xs MExpr
ys -> MExpr
mapE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
zipE MExpr -> MExpr -> MExpr
`a` MExpr
xs MExpr -> MExpr -> MExpr
`a` MExpr
ys))
     (\MExpr
f MExpr
xs MExpr
ys -> MExpr
zipWithE MExpr -> MExpr -> MExpr
`a` (MExpr
curryE MExpr -> MExpr -> MExpr
`a` MExpr
f) MExpr -> MExpr -> MExpr
`a` MExpr
xs MExpr -> MExpr -> MExpr
`a` MExpr
ys),
  -- zipWith (,) --> zip (,)
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (MExpr
zipWithE MExpr -> MExpr -> MExpr
`a` MExpr
commaE) MExpr
zipE,

  -- all f --> and . map f
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
allE MExpr -> MExpr -> MExpr
`a` MExpr
f)
     (\MExpr
f -> MExpr
andE MExpr -> MExpr -> MExpr
`c` MExpr
mapE MExpr -> MExpr -> MExpr
`a` MExpr
f),
  -- and . map f --> all f
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
andE MExpr -> MExpr -> MExpr
`c` MExpr
mapE MExpr -> MExpr -> MExpr
`a` MExpr
f)
     (\MExpr
f -> MExpr
allE MExpr -> MExpr -> MExpr
`a` MExpr
f),
  -- any f --> or . map f
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
anyE MExpr -> MExpr -> MExpr
`a` MExpr
f)
     (\MExpr
f -> MExpr
orE MExpr -> MExpr -> MExpr
`c` MExpr
mapE MExpr -> MExpr -> MExpr
`a` MExpr
f),
  -- or . map f --> any f
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
orE MExpr -> MExpr -> MExpr
`c` MExpr
mapE MExpr -> MExpr -> MExpr
`a` MExpr
f)
     (\MExpr
f -> MExpr
anyE MExpr -> MExpr -> MExpr
`a` MExpr
f),

  -- return f `ap` x --> fmap f x
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x -> MExpr
apE MExpr -> MExpr -> MExpr
`a` (MExpr
returnE MExpr -> MExpr -> MExpr
`a` MExpr
f) MExpr -> MExpr -> MExpr
`a` MExpr
x)
     (\MExpr
f MExpr
x -> MExpr
fmapIE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x),
  -- ap (f `fmap` x) --> liftM2 f x
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x -> MExpr
apE MExpr -> MExpr -> MExpr
`a` (MExpr
fmapIE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x))
     (\MExpr
f MExpr
x -> MExpr
liftM2E MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x),
  -- f `ap` x --> (`fmap` x) =<< f
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x -> MExpr
apE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x)
     (\MExpr
f MExpr
x -> MExpr
extE MExpr -> MExpr -> MExpr
`a` (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
fmapIE MExpr -> MExpr -> MExpr
`a` MExpr
x) MExpr -> MExpr -> MExpr
`a` MExpr
f),
  -- (`fmap` x) =<< f --> f `ap` x
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x -> MExpr
extE MExpr -> MExpr -> MExpr
`a` (MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
fmapIE MExpr -> MExpr -> MExpr
`a` MExpr
x) MExpr -> MExpr -> MExpr
`a` MExpr
f)
     (\MExpr
f MExpr
x -> MExpr
apE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x),
  -- (x >>=) . flip (fmap . f) -> liftM2 f x
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x -> MExpr
bindE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`c` MExpr
flipE MExpr -> MExpr -> MExpr
`a` (MExpr
fmapE MExpr -> MExpr -> MExpr
`c` MExpr
f))
     (\MExpr
f MExpr
x -> MExpr
liftM2E MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x),

  -- (f =<< m) x --> f (m x) x
  (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f MExpr
m MExpr
x -> MExpr
extE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
m MExpr -> MExpr -> MExpr
`a` MExpr
x)
      (\MExpr
f MExpr
m MExpr
x -> MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
m MExpr -> MExpr -> MExpr
`a` MExpr
x) MExpr -> MExpr -> MExpr
`a` MExpr
x),
  -- (fmap f g x) --> f (g x)
  (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f MExpr
g MExpr
x -> MExpr
fmapE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
g MExpr -> MExpr -> MExpr
`a` MExpr
x)
      (\MExpr
f MExpr
g MExpr
x -> MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
g MExpr -> MExpr -> MExpr
`a` MExpr
x)),
  -- return x y --> y
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
y MExpr
x -> MExpr
returnE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
y)
      (\MExpr
y MExpr
_ -> MExpr
y),
  -- liftM2 f g h x --> g x `h` h x
  (MExpr -> MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
f MExpr
g MExpr
h MExpr
x -> MExpr
liftM2E MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
g MExpr -> MExpr -> MExpr
`a` MExpr
h MExpr -> MExpr -> MExpr
`a` MExpr
x)
      (\MExpr
f MExpr
g MExpr
h MExpr
x -> MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
g MExpr -> MExpr -> MExpr
`a` MExpr
x) MExpr -> MExpr -> MExpr
`a` (MExpr
h MExpr -> MExpr -> MExpr
`a` MExpr
x)),
  -- ap f id --> join f
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr  (\MExpr
f -> MExpr
apE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
idE)
      (\MExpr
f -> MExpr
joinE MExpr -> MExpr -> MExpr
`a` MExpr
f),

  -- (=<<) const q --> flip (>>) q
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ -- ??
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
q MExpr
p -> MExpr
extE MExpr -> MExpr -> MExpr
`a` (MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
q) MExpr -> MExpr -> MExpr
`a` MExpr
p)
     (\MExpr
q MExpr
p -> MExpr
seqME MExpr -> MExpr -> MExpr
`a` MExpr
p MExpr -> MExpr -> MExpr
`a` MExpr
q),
  -- p >> q --> const q =<< p
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
p MExpr
q -> MExpr
seqME MExpr -> MExpr -> MExpr
`a` MExpr
p MExpr -> MExpr -> MExpr
`a` MExpr
q)
     (\MExpr
p MExpr
q -> MExpr
extE MExpr -> MExpr -> MExpr
`a` (MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
q) MExpr -> MExpr -> MExpr
`a` MExpr
p),

  -- experimental support for Control.Arrow stuff
  -- (costs quite a bit of performance)
  -- uncurry ((. g) . (,) . f) --> f *** g
  (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
g -> MExpr
uncurryE MExpr -> MExpr -> MExpr
`a` ((MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
compE MExpr -> MExpr -> MExpr
`a` MExpr
g) MExpr -> MExpr -> MExpr
`c` MExpr
commaE MExpr -> MExpr -> MExpr
`c` MExpr
f))
     (\MExpr
f MExpr
g -> MExpr
crossE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
g),
  -- uncurry ((,) . f) --> first f
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
uncurryE MExpr -> MExpr -> MExpr
`a` (MExpr
commaE MExpr -> MExpr -> MExpr
`c` MExpr
f))
     (\MExpr
f -> MExpr
firstE MExpr -> MExpr -> MExpr
`a` MExpr
f),
  -- uncurry ((. g) . (,)) --> second g
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
g -> MExpr
uncurryE MExpr -> MExpr -> MExpr
`a` ((MExpr
flipE MExpr -> MExpr -> MExpr
`a` MExpr
compE MExpr -> MExpr -> MExpr
`a` MExpr
g) MExpr -> MExpr -> MExpr
`c` MExpr
commaE))
     (\MExpr
g -> MExpr
secondE MExpr -> MExpr -> MExpr
`a` MExpr
g),
  -- I think we need all three of them:
  -- uncurry (const f) --> f . snd
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
uncurryE MExpr -> MExpr -> MExpr
`a` (MExpr
constE MExpr -> MExpr -> MExpr
`a` MExpr
f))
     (\MExpr
f -> MExpr
f MExpr -> MExpr -> MExpr
`c` MExpr
sndE),
  -- uncurry const --> fst
  MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (MExpr
uncurryE MExpr -> MExpr -> MExpr
`a` MExpr
constE)
     (MExpr
fstE),
  -- uncurry (const . f) --> f . fst
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
uncurryE MExpr -> MExpr -> MExpr
`a` (MExpr
constE MExpr -> MExpr -> MExpr
`c` MExpr
f))
     (\MExpr
f -> MExpr
f MExpr -> MExpr -> MExpr
`c` MExpr
fstE),

  -- TODO is this the right place?
  -- [x] --> return x
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
x -> MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
nilE)
     (\MExpr
x -> MExpr
returnE MExpr -> MExpr -> MExpr
`a` MExpr
x),
  -- list destructors
  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$
  RewriteRule -> RewriteRule -> RewriteRule
If ([RewriteRule] -> RewriteRule
Or [MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr MExpr
consE MExpr
consE, MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr MExpr
nilE MExpr
nilE]) (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ [RewriteRule] -> RewriteRule
Or [
    RewriteRule -> RewriteRule
down (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ [RewriteRule] -> RewriteRule
Or [
      -- length [] --> 0
      MExpr -> MExpr -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (MExpr
lengthE MExpr -> MExpr -> MExpr
`a` MExpr
nilE)
         MExpr
zeroE,
      -- length (x:xs) --> 1 + length xs
      (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
x MExpr
xs -> MExpr
lengthE MExpr -> MExpr -> MExpr
`a` (MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
xs))
         (\MExpr
_ MExpr
xs -> MExpr
plusE MExpr -> MExpr -> MExpr
`a` MExpr
oneE MExpr -> MExpr -> MExpr
`a` (MExpr
lengthE MExpr -> MExpr -> MExpr
`a` MExpr
xs))
    ],
    -- map/fmap elimination
    RewriteRule -> RewriteRule
down (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ [RewriteRule] -> RewriteRule
Or [
      -- map f (x:xs) --> f x: map f xs
      (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x MExpr
xs -> MExpr
mapE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
xs))
         (\MExpr
f MExpr
x MExpr
xs -> MExpr
consE MExpr -> MExpr -> MExpr
`a` (MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x) MExpr -> MExpr -> MExpr
`a` (MExpr
mapE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
xs)),
      -- fmap f (x:xs) --> f x: Fmap f xs
      (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x MExpr
xs -> MExpr
fmapE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
xs))
         (\MExpr
f MExpr
x MExpr
xs -> MExpr
consE MExpr -> MExpr -> MExpr
`a` (MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x) MExpr -> MExpr -> MExpr
`a` (MExpr
fmapE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
xs)),
      -- map f []     --> []
      (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
mapE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
nilE)
         (\MExpr
_ -> MExpr
nilE),
      -- fmap f []     --> []
      (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f -> MExpr
fmapE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
nilE)
         (\MExpr
_ -> MExpr
nilE)
    ],
    -- foldr elimination
    RewriteRule -> RewriteRule
down (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ [RewriteRule] -> RewriteRule
Or [
      -- foldr f z (x:xs) --> f x (foldr f z xs)
      (MExpr -> MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x MExpr
xs MExpr
z -> (MExpr
foldrE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
z) MExpr -> MExpr -> MExpr
`a` (MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
xs))
         (\MExpr
f MExpr
x MExpr
xs MExpr
z -> (MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x) MExpr -> MExpr -> MExpr
`a` (MExpr
foldrE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
z MExpr -> MExpr -> MExpr
`a` MExpr
xs)),
      -- foldr f z [] --> z
      (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
z -> MExpr
foldrE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
z MExpr -> MExpr -> MExpr
`a` MExpr
nilE)
         (\MExpr
_ MExpr
z -> MExpr
z)
    ],
    -- foldl elimination
    RewriteRule -> RewriteRule
down (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ RewriteRule -> RewriteRule
Opt ((Expr -> Maybe Expr) -> RewriteRule
CRR ((Expr -> Maybe Expr) -> RewriteRule)
-> (Expr -> Maybe Expr) -> RewriteRule
forall a b. (a -> b) -> a -> b
$ [[Char]] -> Expr -> Maybe Expr
assocL [[Char]
"."]) RewriteRule -> RewriteRule -> RewriteRule
`Then` [RewriteRule] -> RewriteRule
Or [
      -- sum xs --> foldl (+) 0 xs
      (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
xs -> MExpr
sumE MExpr -> MExpr -> MExpr
`a` MExpr
xs)
         (\MExpr
xs -> MExpr
foldlE MExpr -> MExpr -> MExpr
`a` MExpr
plusE MExpr -> MExpr -> MExpr
`a` MExpr
zeroE MExpr -> MExpr -> MExpr
`a` MExpr
xs),
      -- product xs --> foldl (*) 1 xs
      (MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
xs -> MExpr
productE MExpr -> MExpr -> MExpr
`a` MExpr
xs)
         (\MExpr
xs -> MExpr
foldlE MExpr -> MExpr -> MExpr
`a` MExpr
multE MExpr -> MExpr -> MExpr
`a` MExpr
oneE MExpr -> MExpr -> MExpr
`a` MExpr
xs),
      -- foldl1 f (x:xs) --> foldl f x xs
      (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
x MExpr
xs -> MExpr
foldl1E MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
xs))
         (\MExpr
f MExpr
x MExpr
xs -> MExpr
foldlE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
xs),
      -- foldl f z (x:xs) --> foldl f (f z x) xs
      (MExpr -> MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
z MExpr
x MExpr
xs -> (MExpr
foldlE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
z) MExpr -> MExpr -> MExpr
`a` (MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
xs))
         (\MExpr
f MExpr
z MExpr
x MExpr
xs -> MExpr
foldlE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` (MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
z MExpr -> MExpr -> MExpr
`a` MExpr
x) MExpr -> MExpr -> MExpr
`a` MExpr
xs),
      -- foldl f z [] --> z
      (MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
z -> MExpr
foldlE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
z MExpr -> MExpr -> MExpr
`a` MExpr
nilE)
         (\MExpr
_ MExpr
z -> MExpr
z),
      -- special rule:
      -- foldl f z [x] --> f z x
      (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
z MExpr
x -> MExpr
foldlE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
z MExpr -> MExpr -> MExpr
`a` (MExpr
returnE MExpr -> MExpr -> MExpr
`a` MExpr
x))
         (\MExpr
f MExpr
z MExpr
x -> MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
z MExpr -> MExpr -> MExpr
`a` MExpr
x),
      (MExpr -> MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr (\MExpr
f MExpr
z MExpr
x -> MExpr
foldlE MExpr -> MExpr -> MExpr
`a` MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
z MExpr -> MExpr -> MExpr
`a` (MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
nilE))
         (\MExpr
f MExpr
z MExpr
x -> MExpr
f MExpr -> MExpr -> MExpr
`a` MExpr
z MExpr -> MExpr -> MExpr
`a` MExpr
x)
    ] RewriteRule -> RewriteRule -> RewriteRule
`OrElse` (
      -- (:) x --> (++) [x]
      RewriteRule -> RewriteRule
Opt ((MExpr -> MExpr) -> (MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
x -> MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x)
         (\MExpr
x -> MExpr
appendE MExpr -> MExpr -> MExpr
`a` (MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
nilE))) RewriteRule -> RewriteRule -> RewriteRule
`Then`
      -- More special rule: (:) x . (++) ys --> (++) (x:ys)
      RewriteRule -> RewriteRule
up ((MExpr -> MExpr -> MExpr)
-> (MExpr -> MExpr -> MExpr) -> RewriteRule
forall a. RewriteC a => a -> a -> RewriteRule
rr0 (\MExpr
x MExpr
ys -> (MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x) MExpr -> MExpr -> MExpr
`c` (MExpr
appendE MExpr -> MExpr -> MExpr
`a` MExpr
ys))
         (\MExpr
x MExpr
ys -> MExpr
appendE MExpr -> MExpr -> MExpr
`a` (MExpr
consE MExpr -> MExpr -> MExpr
`a` MExpr
x MExpr -> MExpr -> MExpr
`a` MExpr
ys)))
      )
  ],

  -- Complicated Transformations
  (Expr -> Maybe Expr) -> RewriteRule
CRR (Expr -> Maybe Expr
collapseLists),
  RewriteRule -> RewriteRule
up (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ [RewriteRule] -> RewriteRule
Or [(Expr -> Maybe Expr) -> RewriteRule
CRR ([([Char], Unary)] -> Expr -> Maybe Expr
evalUnary [([Char], Unary)]
unaryBuiltins), (Expr -> Maybe Expr) -> RewriteRule
CRR ([([Char], Binary)] -> Expr -> Maybe Expr
evalBinary [([Char], Binary)]
binaryBuiltins)],
  RewriteRule -> RewriteRule
up (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ (Expr -> Maybe Expr) -> RewriteRule
CRR ([[Char]] -> Expr -> Maybe Expr
assoc [[Char]]
assocOps),
  RewriteRule -> RewriteRule
up (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ (Expr -> Maybe Expr) -> RewriteRule
CRR ([[Char]] -> Expr -> Maybe Expr
assocL [[Char]]
assocOps),
  RewriteRule -> RewriteRule
up (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ (Expr -> Maybe Expr) -> RewriteRule
CRR ([[Char]] -> Expr -> Maybe Expr
assocR [[Char]]
assocOps),
  RewriteRule -> RewriteRule -> RewriteRule
Up ((Expr -> Maybe Expr) -> RewriteRule
CRR ([[Char]] -> Expr -> Maybe Expr
commutative [[Char]]
commutativeOps)) (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ RewriteRule -> RewriteRule
down (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ [RewriteRule] -> RewriteRule
Or [(Expr -> Maybe Expr) -> RewriteRule
CRR ((Expr -> Maybe Expr) -> RewriteRule)
-> (Expr -> Maybe Expr) -> RewriteRule
forall a b. (a -> b) -> a -> b
$ [[Char]] -> Expr -> Maybe Expr
assocL [[Char]]
assocLOps,
                                                     (Expr -> Maybe Expr) -> RewriteRule
CRR ((Expr -> Maybe Expr) -> RewriteRule)
-> (Expr -> Maybe Expr) -> RewriteRule
forall a b. (a -> b) -> a -> b
$ [[Char]] -> Expr -> Maybe Expr
assocR [[Char]]
assocROps],

  RewriteRule -> RewriteRule
Hard (RewriteRule -> RewriteRule) -> RewriteRule -> RewriteRule
forall a b. (a -> b) -> a -> b
$ RewriteRule
simplifies
  ] RewriteRule -> RewriteRule -> RewriteRule
`Then` RewriteRule -> RewriteRule
Opt (RewriteRule -> RewriteRule
up RewriteRule
simplifies)

----------------------------------------------------------------------------------------
-- Operator information

assocLOps, assocROps, assocOps :: [String]
assocLOps :: [[Char]]
assocLOps = [[Char]
"+", [Char]
"*", [Char]
"&&", [Char]
"||", [Char]
"max", [Char]
"min"]
assocROps :: [[Char]]
assocROps = [[Char]
".", [Char]
"++"]
assocOps :: [[Char]]
assocOps  = [[Char]]
assocLOps [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]]
assocROps

commutativeOps :: [String]
commutativeOps :: [[Char]]
commutativeOps = [[Char]
"*", [Char]
"+", [Char]
"==", [Char]
"/=", [Char]
"max", [Char]
"min"]

unaryBuiltins :: [(String,Unary)]
unaryBuiltins :: [([Char], Unary)]
unaryBuiltins = [
    ([Char]
"not",    (Bool -> Bool) -> Unary
forall a b. (Read a, Show a, Read b, Show b) => (a -> b) -> Unary
UA (Bool -> Bool
not    :: Bool -> Bool)),
    ([Char]
"negate", (Integer -> Integer) -> Unary
forall a b. (Read a, Show a, Read b, Show b) => (a -> b) -> Unary
UA (Integer -> Integer
forall a. Num a => a -> a
negate :: Integer -> Integer)),
    ([Char]
"signum", (Integer -> Integer) -> Unary
forall a b. (Read a, Show a, Read b, Show b) => (a -> b) -> Unary
UA (Integer -> Integer
forall a. Num a => a -> a
signum :: Integer -> Integer)),
    ([Char]
"abs",    (Integer -> Integer) -> Unary
forall a b. (Read a, Show a, Read b, Show b) => (a -> b) -> Unary
UA (Integer -> Integer
forall a. Num a => a -> a
abs    :: Integer -> Integer))
  ]

binaryBuiltins :: [(String,Binary)]
binaryBuiltins :: [([Char], Binary)]
binaryBuiltins = [
    ([Char]
"+",    (Integer -> Integer -> Integer) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(+)  :: Integer -> Integer -> Integer)),
    ([Char]
"-",    (Integer -> Integer -> Integer) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA ((-)  :: Integer -> Integer -> Integer)),
    ([Char]
"*",    (Integer -> Integer -> Integer) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(*)  :: Integer -> Integer -> Integer)),
    ([Char]
"^",    (Integer -> Integer -> Integer) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
(^)  :: Integer -> Integer -> Integer)),
    ([Char]
"<",    (Integer -> Integer -> Bool) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
(<)  :: Integer -> Integer -> Bool)),
    ([Char]
">",    (Integer -> Integer -> Bool) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
(>)  :: Integer -> Integer -> Bool)),
    ([Char]
"==",   (Integer -> Integer -> Bool) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
(==) :: Integer -> Integer -> Bool)),
    ([Char]
"/=",   (Integer -> Integer -> Bool) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
(/=) :: Integer -> Integer -> Bool)),
    ([Char]
"<=",   (Integer -> Integer -> Bool) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
(<=) :: Integer -> Integer -> Bool)),
    ([Char]
">=",   (Integer -> Integer -> Bool) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
(>=) :: Integer -> Integer -> Bool)),
    ([Char]
"div",  (Integer -> Integer -> Integer) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
div  :: Integer -> Integer -> Integer)),
    ([Char]
"mod",  (Integer -> Integer -> Integer) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
mod  :: Integer -> Integer -> Integer)),
    ([Char]
"max",  (Integer -> Integer -> Integer) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
max  :: Integer -> Integer -> Integer)),
    ([Char]
"min",  (Integer -> Integer -> Integer) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
min  :: Integer -> Integer -> Integer)),
    ([Char]
"&&",   (Bool -> Bool -> Bool) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Bool -> Bool -> Bool
(&&) :: Bool -> Bool -> Bool)),
    ([Char]
"||",   (Bool -> Bool -> Bool) -> Binary
forall a b c.
(Read a, Show a, Read b, Show b, Read c, Show c) =>
(a -> b -> c) -> Binary
BA (Bool -> Bool -> Bool
(||) :: Bool -> Bool -> Bool))
  ]