2

I'm currently studying the language OCaml, and was solving an exercise problem when I came across a question that I can't seem to wrap my head around. Here's the question:


"Write a function differentiate : expression * string -> expression that receives an algebraic equation and a string as an argument, and returns the differentiated version of the argument equation.

For example, diff (Add [Mult [Int 3 ; Exp("x", 2)] ; Mult [Int 6 ; Variable "x"], "x") should produce the result:

Add [Mult [Int 6 ; Variable "x"] ; Int 6]"


Here's the code that I wrote:

type expression =
  | Int of int
  | Variable of string
  | Exponent of string * int
  | Mult of expression list
  | Add of expression list


let rec differentiate : expression * string -> expression
= fun (exp, x) ->
  match exp with
  | Int a -> Int 0
  | Variable a -> if (a = x) then Int 1 else Variable a
  | Exponent (a, b) -> if (a = x) then
                      match b with
                      | 2 -> Mult [Int 2; Variable a]
                      | _ -> Mult [Int b; Exponent (a, b - 1)]
                    else Int 0
  | Mult [Int a; Int b] -> Const (a * b)
  | Mult (Int a::[Variable b]) -> Mult (Int a::[differentiate (Variable b, x)])
  | Mult (Int a::[Exponent (e1, e2)]) -> Mult (Int a::[differentiate (Exponent (e1, e2), 
x)])
  | Mult (Int a::[Mult (Int b :: l)]) -> Mult (Int (a * b) :: l)
  | Add l -> match l with
             | [] -> l
             | hd::tl -> Add ((differentiate (hd, x)) :: tl)
;;


My algorithm is basically performing rigorous pattern matching. More specifically, for Mult, the first element is always an integer, so I performed pattern matching on the second element. For Add, my plan was to write the function so that it performs the function differentiate on each element. Here are the specific problems I would like to ask about.

  1. This code actually gives me an error on the Add l portion of pattern matching. The error message states: Error: This expression has type (expression list) but an expression was expected of type (expression). As far as my understanding reaches, I am certain that Add l is an expression type, not an expression list type. Why is this error message produced?

  2. I am not sure how to perform recursion in this specific example. My initial thought is that the function should only execute once each, otherwise the result would consist mainly of Int 0's or Int 1's. Please correct me if I'm wrong.


Any feedback is greatly appreciated. Thank you!

Sean
  • 2,890
  • 8
  • 36
  • 78
  • 2
    For problem 1, you probably need to wrap the nested `match` in parentheses or `begin ... end`. OCaml is not whitespace sensitive, and will probably not associate the branches to the match expressions you expect it to. – glennsl Oct 10 '18 at 09:43
  • 2
    You should not ask multiple questions in the same post, btw, and preferably reduce the code to the minimal that is necessary to illustrate the problem (which is easier if you don't need context for multiple questions). Otherwise this is a good, clear and detailed, question! – glennsl Oct 10 '18 at 09:47
  • Hello @glennsl thanks for the nice comment. I'll keep the feedback in mind for future questions! :) Regarding your suggestion, unfortunately wrapping the match sequence in parentheses or `begin ... end` did not solve the problem... :( I appreciate the suggestion, though. – Sean Oct 10 '18 at 09:57
  • 3
    Oh, I guess it doesn't matter if the nested match is on the last branch. Your problem is instead that your return a list `l` in the first branch, and a single `expression` in the second. Unfortunately I don't have time to study your problem enough to be able to suggest a solution. – glennsl Oct 10 '18 at 10:07
  • 1
    Actually, your comment gave me the right hint haha. The right-hand side of the first match case was `l` and changing it to `Sum l` fixed the problem. Thank you! – Sean Oct 10 '18 at 10:11
  • 1
    I think you should separate your concerns. Write one plain simple function that does a correct differentiation for *all* possible inputs. Write a second function that handles optimisation/reduction. Then compose the results. Consider your input example where you have to simplify `diff (3*x^2)` via `3*2*x^1` to `6*x` – mschmidt Oct 10 '18 at 17:54
  • Thanks! I think that would make it much simpler to implement it... It seems a bit too difficult to implement a single function that performs differentiation and "cleaning up." – Sean Oct 11 '18 at 01:36

0 Answers0