1


I encounter a problem with a optional argument in a method class.

let me explain. I have a pathfinding class graph (in the Wally module) and one his method shorthestPath. It use a optional argument. The fact is when I call (with or not the optional argument) this method OCaml return a conflict of type :

Error: This expression has type Wally.graph
   but an expression was expected of type
     < getCoor : string -> int * int;
       getNearestNode : int * int -> string;
       shorthestPath : src:string -> string -> string list; .. >
   Types for method shorthestPath are incompatible

whereas shorthestPath type is :

method shorthestPath : ?src:string -> string -> string list

I same tried to use the option format for a optional argument :

method shorthestPath ?src dst =
  let source = match src with
    | None -> currentNode
    | Some node -> node
  in 
  ...

Only in the case where I remove the optionnal argument, OCaml stop to insult me.

Thank you in advance for your help :)

Phil Gekni
  • 21
  • 3

1 Answers1

7

It is not very clear what your situation is but I guess the following:

let f o = o#m 1 + 2

let o = object method m ?l x = match l with Some y -> x + y | None -> x

let () = print_int (f o)   (* type error. Types for method x are incompatible. *)

The use site (here the definition of f), the type of object is inferred from its context. Here, o : < x : int -> int; .. >. The method x's type is fixed here.

The object o defined later is independent from the argument of f and has the type < m : ?l:int -> int -> int; .. >. And unfortunately this type is incompatible with the other.

A workaround is to give more typing context to the use site about the optional argument:

let f o = o#m ?l:None 1 + 2  (* Explicitly telling there is l *)
let o = object method m ?l x = match l with Some y -> x + y | None -> x end

Or give the type of o:

class c = object
    method m ?l x = ...
    ...
end

let f (o : #c) = o#m 1 + 2   (* Not (o : c) but (o : #c) to get the function more polymoprhic *)
let o = new c
let () = print_int (f o)

I think this is easier since there is usually a class declaration beforehand.

This kind of glitch between higher order use of functions with optional arguments happens also outside of objects. OCaml tries to resolve it nicely but it is not always possible. In this case:

let f g = g 1 + 2
let g ?l x = match l with Some y -> x + y | None -> x
let () = print_int (f g)

is nicely typed. Nice!

The key rule: if OCaml cannot infer about omitted optional arguments, try giving some type context about them explicitly.

camlspotter
  • 8,990
  • 23
  • 27
  • Explicit context... Effectively, I think the best method is to use the interface for each module. However, my project is too far advanced to do that and I haven't much time. But for now force the type of my variable might well be applicable. So with this code I have no problem: `let path = self#getNodes#shorthestPath node in ...` with `method private getNodes = match nodes with Some n -> (n:Wally.graph) | None -> failwith "Pathfinding is not initialized"` – Phil Gekni Jun 20 '13 at 23:55
  • Thank you very much for your help. And sorry for my lack of clarity. – Phil Gekni Jun 20 '13 at 23:56