odeMotion3 :: forall dom m a
    .  ( ConstrainedBy dom Typeable
       , AlphaEq dom dom dom [(VarId,VarId)]
       , Project Let dom
       , MonadState VarId m
       )
    => Int  -- Max number of iterations
    -> (forall c. ASTF dom c -> Bool)
         -- ^ Control wether a sub-expression can be hoisted over the given expression
    -> PrjDict dom
    -> MkInjDict dom
    -> MkSubEnv dom
    -> ASTF dom a
    -> m (ASTF dom a)
codeMotion3 limit hoistOver pd mkId mkSub = fixIter limit $ codeMotion hoistOver pd mkId mkSub

codeMotion3 :: forall dom m a
    .  ( ConstrainedBy dom Typeable
       , AlphaEq dom dom dom [(VarId,VarId)]
       , Project Let dom
       , MonadState VarId m
       )
    => Int  -- Max number of iterations
    -> (forall c. ASTF dom c -> Bool)
         -- ^ Control wether a sub-expression can be hoisted over the given expression
    -> PrjDict dom
    -> MkInjDict dom
    -> MkSubEnv dom
    -> ASTF dom a
    -> m (ASTF dom a)
codeMotion3 limit hoistOver pd mkId mkSub = fixIter limit $ codeMotion hoistOver pd mkId mkSub
codeMotion3 limit hoistOver pd mkId mkSub = fixIter limit $ codeMotion hoistOver pd mkId mkSub