Search code examples
sml

Why am i getting the "match redudant" error?


I am a bit confused about the "match redundant" error i am getting when running the following code :

    datatype expression =  Constant of int |
            Variable of string |
            Operator of string * expression |
            Pair of expression list |
            List of expression list

fun add2 (ul1: expression, ul2: expression) =
    let
        fun gcd (a, b) =
            if a >= b
            then 
                if (a mod b) = 0
                then b
                else gcd (b,(a mod b))
            else
            if (b mod a) = 0
            then a
            else gcd (a, (b mod a))
        fun lcm (a,b) =
            a*b div (gcd(a,b))      
    in

        case ul1 of
            Operator("/",Pair [Constant a, Constant b]) =>
                case ul2 of
                    Operator("/",Pair [Constant c, Constant d]) => 
                    a*d + c*b//(b*d)
                    |Operator("/",Pair [Variable c, Constant d])=>
                    Operator("/",Pair [(Operator("+", Pair [Constant a, Variable c])),Constant (lcm(b,d))])

            |Operator("/",Pair [Variable a, Constant b]) =>
                case ul2 of
                    Operator("/",Pair [Constant c, Constant d]) => 
                    Operator("/",Pair [(Operator("+", Pair [Variable a, Constant c])),Constant (lcm(b,d))])
                    |Operator("/",Pair [Variable c, Constant d])=>
                    Operator("/",Pair [(Operator("+", Pair [Variable a, Variable c])),Constant (lcm(b,d))])


    end

The exact error massage is :

C:\Users\erikj\Dropbox\Fakulteta Laptop\Programiranje\domacanaloga 6.sml:91.5-102.93 Error: match redundant and nonexhaustive
          Operator ("/",Pair (Constant c :: Constant d :: nil)) => ...
          Operator ("/",Pair (Variable c :: Constant d :: nil)) => ...
    -->   Operator ("/",Pair (Variable a :: Constant b :: nil)) => ...

I dont mind about the nonexhaustive matches since it is just an excercise. Thank you for your help in advance !


Solution

  • Consider the following code:

    case ul1 of
        Operator("/",Pair [Constant a, Constant b]) =>
            case ul2 of
                Operator("/",Pair [Constant c, Constant d]) => 
                ...
                |Operator("/",Pair [Variable c, Constant d])=> (* Case A *)
                ...
                |Operator("/",Pair [Variable a, Constant b]) => (* Case B *)
                ...
    

    It should be pretty clear that case B is redundant because it is the same as case A (except for the variable names).

    The only change between this code and your code is that I changed the indentation of case B. Now indentation does not affect the semantics of SML programs, so case B is just as redundant in your code as it is here.

    To a human reader it is clear from the indentation that you intended case B to belong to the outer pattern match, but, as I said, the compiler doesn't care about indentation, so you'll need to use parentheses or begin-end blocks to tell the compiler where the inner match ends.