minRawKind :: Monad m => String -> RawKind -> RawKind -> m RawKind
minRawKind str k1 k2 = let err = fail $ diffKindString str k1 k2 in case k1 of
    ClassKind _ -> case k2 of
        ClassKind _ -> return $ ClassKind ()
        _ -> err
    FunKind v1 a1 r1 ps -> case k2 of
        FunKind v2 a2 r2 qs -> do
            a3 <- minRawKind str a2 a1
            r3 <- minRawKind str r1 r2
            return $ FunKind (minVariance v1 v2) a3 r3 $ appRange ps qs
        _ -> err
minRawKind :: Monad m => String -> RawKind -> RawKind -> m RawKind
minRawKind str k1 k2 = let err = fail $ diffKindString str k1 k2 in case k1 of
    ClassKind _ -> case k2 of
        ClassKind _ -> return $ ClassKind ()
        _ -> err
    FunKind v1 a1 r1 ps -> case k2 of
        FunKind v2 a2 r2 qs -> do
            a3 <- minRawKind str a2 a1
            r3 <- minRawKind str r1 r2
            return $ FunKind (minVariance v1 v2) a3 r3 $ appRange ps qs
        _ -> err
minRawKind str k1 k2 = let err = fail $ diffKindString str k1 k2 in case k1 of
    ClassKind _ -> case k2 of
        ClassKind _ -> return $ ClassKind ()
        _ -> err
    FunKind v1 a1 r1 ps -> case k2 of
        FunKind v2 a2 r2 qs -> do
            a3 <- minRawKind str a2 a1
            r3 <- minRawKind str r1 r2
            return $ FunKind (minVariance v1 v2) a3 r3 $ appRange ps qs
        _ -> err