patClean (PTuple p1 p2) = fstClean ++ sndClean ++ swapClean where
    fstClean = do
        (p, c) <- patClean p1
        let cln (AppOp2 OpPair e1 e2) = AppOp2 OpPair <$> c e1 <*> pure e2
            cln _ = Nothing
        return (PTuple p p2, cln)
    sndClean = do
        (p, c) <- patClean p2
        let cln (AppOp2 OpPair e1 e2) = AppOp2 OpPair <$> pure e1 <*> c e2
            cln _ = Nothing
        return (PTuple p1 p, cln)
    swapClean = do
        let cln (AppOp1 OpSwap e) = pure e
            cln _ = Nothing
        return (PTuple p2 p1, cln)
patClean (PTuple p1 p2) = fstClean ++ sndClean ++ swapClean where
    fstClean = do
        (p, c) <- patClean p1
        let cln (AppOp2 OpPair e1 e2) = AppOp2 OpPair <$> c e1 <*> pure e2
            cln _ = Nothing
        return (PTuple p p2, cln)
    sndClean = do
        (p, c) <- patClean p2
        let cln (AppOp2 OpPair e1 e2) = AppOp2 OpPair <$> pure e1 <*> c e2
            cln _ = Nothing
        return (PTuple p1 p, cln)
    swapClean = do
        let cln (AppOp1 OpSwap e) = pure e
            cln _ = Nothing
        return (PTuple p2 p1, cln)
patClean (PTuple p1 p2) = fstClean ++ sndClean ++ swapClean where
    fstClean = do
        (p, c) <- patClean p1
        let cln (AppOp2 OpPair e1 e2) = AppOp2 OpPair <$> c e1 <*> pure e2
            cln _ = Nothing
        return (PTuple p p2, cln)
    sndClean = do
        (p, c) <- patClean p2
        let cln (AppOp2 OpPair e1 e2) = AppOp2 OpPair <$> pure e1 <*> c e2
            cln _ = Nothing
        return (PTuple p1 p, cln)
    swapClean = do
        let cln (AppOp1 OpSwap e) = pure e
            cln _ = Nothing
        return (PTuple p2 p1, cln)