ssa :: (MonadOhua m, MonadReader LocalScope m)
    => Expression
    -> m Expression
ssa =
    cata $ \case
        VarF bnd -> Var <$> ssaResolve bnd
        LambdaF v body -> ssaRename v $ \v' -> Lambda v' <$> body
        LetF v val body -> ssaRename v $ \v' -> Let v' <$> val <*> body
        e -> embed <$> sequence e

-- Check if an expression is in ssa form. Returns @Nothing@ if it is
-- SSA Returns @Just aBinding@ where @aBinding@ is a binding which was
-- defined (at least) twice
ssa :: (MonadOhua m, MonadReader LocalScope m)
    => Expression
    -> m Expression
ssa =
    cata $ \case
        VarF bnd -> Var <$> ssaResolve bnd
        LambdaF v body -> ssaRename v $ \v' -> Lambda v' <$> body
        LetF v val body -> ssaRename v $ \v' -> Let v' <$> val <*> body
        e -> embed <$> sequence e

-- Check if an expression is in ssa form. Returns @Nothing@ if it is
-- SSA Returns @Just aBinding@ where @aBinding@ is a binding which was
-- defined (at least) twice
ssa =
    cata $ \case
        VarF bnd -> Var <$> ssaResolve bnd
        LambdaF v body -> ssaRename v $ \v' -> Lambda v' <$> body
        LetF v val body -> ssaRename v $ \v' -> Let v' <$> val <*> body
        e -> embed <$> sequence e

-- Check if an expression is in ssa form. Returns @Nothing@ if it is
-- SSA Returns @Just aBinding@ where @aBinding@ is a binding which was
-- defined (at least) twice