Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variant, Recursive Function and Type Inference

I'm very new at OCaml but worked all the past two days in order to get a good understanding of how to use it. I've been doing a lot of thing lately but something is keeping me from moving forward.

I'm trying to implement an evalexpr in OCaml. Pretty easy using this langage you would say : so I thought, and the first I did, using regular ints, worked fine. But now I'm trying to do so using my OWN type and my own functions to solve operations : and of course it's not as easy as I expected.

type expr =
  | Number of MyInt.myint
  | Sum of (expr * expr)
  | Sub of (expr * expr)
  | Product of (expr * expr)
  | Divide of (expr * expr)
  | Modulo of (expr * expr)

let rec evalexpr expr = function
  | Number n       -> n
  | Sum (a, b)     -> MyInt.add (evalexpr a) (evalexpr b)
  | Sub (a, b)     -> MyInt.sub (evalexpr a) (evalexpr b)
  | Product (a, b) -> MyInt.mul (evalexpr a) (evalexpr b)
  | Divide (a, b)  -> MyInt.div (evalexpr a) (evalexpr b)
  | Modulo (a, b)  -> MyInt.modulo (evalexpr a) (evalexpr b)

This seems ok to me... but the compiler disagrees. I think it's pretty obvious that the "(evalexpr a)" is of type MyInt.myint, as it is the only final return value the evalexpr function can return : still, the compiler think its type is "expr -> MyInt.myint".

Does it means it doesn't apply the function evalexpr and returns the function itself ?? if so, why the hell would it do that ? I just can't figure it out. And I can't think of another way to do what I'm trying to achieve here.

like image 775
The-Snake Avatar asked Aug 25 '26 20:08

The-Snake


2 Answers

Remove expr from your evalexpr function.

let rec evalexpr = function
    ...

By having it there, you are declaring that the function takes 2 paramemters. The first will be bound to the variable expr and the second will be matched in the function body. Then when you try to recursively call it, you call evalexpr with single parameters yielding functions expecting the second parameter. Then naturally your functions cannot operate on functions hence the error.

like image 69
Jeff Mercado Avatar answered Aug 30 '26 10:08

Jeff Mercado


Ok, I think it should be like this:

let rec evalexpr = function
  | Number n       -> n
  | Sum (a, b)     -> MyInt.add (evalexpr a) (evalexpr b)
  | Sub (a, b)     -> MyInt.sub (evalexpr a) (evalexpr b)
  | Product (a, b) -> MyInt.mul (evalexpr a) (evalexpr b)
  | Divide (a, b)  -> MyInt.div (evalexpr a) (evalexpr b)
  | Modulo (a, b)  -> MyInt.modulo (evalexpr a) (evalexpr b)

function statement already takes an argument for you so what you actually declared was a function that takes one argument and returns a function

like image 38
julx Avatar answered Aug 30 '26 08:08

julx



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!