mergeParfor ExpA (LamE vtaus p) = do
    LamE vtaus <$> (fromMnf <$> go (toMnf p))
  where
    go :: Mnf Exp -> m (Mnf Exp)
    go [] =
        return []

    go ((seq1, ForE ParFor [(v1, e1)] p1) : (seq2, ForE ParFor [(v2, e2)] p2) : ms) = do
        insertSubst VarA v2 VarA v1
        let p1' = whenE ((E . VarE) v1 <* (E e1 :: E.Exp t Int32)) p1
        let p2' = whenE ((E . VarE) v1 <* (E e2 :: E.Exp t Int32)) p2
        go ((seq1, ForE ParFor [(v1, BinopE MaxO e1 e2)] (sync p1' p2')) : ms)
      where
        sync = case seq2 of
                 SeqM -> syncE
                 ParM -> seqE
                 _    -> error "mergeParfor: saw bind between parallel fors"

    go ((s,m) : ms) = do
        m'  <- mergeParfor ExpA m
        ms' <- go ms
        return $ (s,m') : ms'
mergeParfor ExpA (LamE vtaus p) = do
    LamE vtaus <$> (fromMnf <$> go (toMnf p))
  where
    go :: Mnf Exp -> m (Mnf Exp)
    go [] =
        return []

    go ((seq1, ForE ParFor [(v1, e1)] p1) : (seq2, ForE ParFor [(v2, e2)] p2) : ms) = do
        insertSubst VarA v2 VarA v1
        let p1' = whenE ((E . VarE) v1 <* (E e1 :: E.Exp t Int32)) p1
        let p2' = whenE ((E . VarE) v1 <* (E e2 :: E.Exp t Int32)) p2
        go ((seq1, ForE ParFor [(v1, BinopE MaxO e1 e2)] (sync p1' p2')) : ms)
      where
        sync = case seq2 of
                 SeqM -> syncE
                 ParM -> seqE
                 _    -> error "mergeParfor: saw bind between parallel fors"

    go ((s,m) : ms) = do
        m'  <- mergeParfor ExpA m
        ms' <- go ms
        return $ (s,m') : ms'
mergeParfor ExpA (LamE vtaus p) = do
    LamE vtaus <$> (fromMnf <$> go (toMnf p))
  where
    go :: Mnf Exp -> m (Mnf Exp)
    go [] =
        return []

    go ((seq1, ForE ParFor [(v1, e1)] p1) : (seq2, ForE ParFor [(v2, e2)] p2) : ms) = do
        insertSubst VarA v2 VarA v1
        let p1' = whenE ((E . VarE) v1 <* (E e1 :: E.Exp t Int32)) p1
        let p2' = whenE ((E . VarE) v1 <* (E e2 :: E.Exp t Int32)) p2
        go ((seq1, ForE ParFor [(v1, BinopE MaxO e1 e2)] (sync p1' p2')) : ms)
      where
        sync = case seq2 of
                 SeqM -> syncE
                 ParM -> seqE
                 _    -> error "mergeParfor: saw bind between parallel fors"

    go ((s,m) : ms) = do
        m'  <- mergeParfor ExpA m
        ms' <- go ms
        return $ (s,m') : ms'