Home > Blockchain >  Is this possible to set a default value of a function without loosing the polymorphic type of an arg
Is this possible to set a default value of a function without loosing the polymorphic type of an arg

Time:11-25

I have this function to add logs in a file :

let log_datas f file (datas: 'a list) = 
  let oc = open_out file.file_name in 
    List.iter (fun x -> Printf.fprintf oc "%s" @@ f x) datas;
    close_out oc

let () = let f = string_of_int in  log_datas f {file_name="log"} [1;2]

Which works.

I tried to make it by default accepting string list as argument :

let log_datas ?(f:'a -> string = fun x -> x^"\n") file (datas: 'a list) = 
  let oc = open_out file.file_name in 
    List.iter (fun x -> Printf.fprintf oc "%s" @@ f x) datas;
    close_out oc

but when I try

let () = let f = string_of_int in  log_datas ~f {file_name="log"} [1;2]

I get a type error

23 | let () = let f = string_of_int in  log_datas ~f {file_name="log"} [1;2]
                                                   ^
Error: This expression has type int -> string
       but an expression was expected of type string -> string
       Type int is not compatible with type string

An obvious solution would be to make 2 function, one with no f argument and one with a f argument. But I was wondering, is there any other workaround possible ?

CodePudding user response:

No, it is not possible, you have to specify both parameters to keep it polymorphic. Basically, your example could be distilled to,

let log ?(to_string=string_of_int) data =
  print_endline (to_string data)

If OCaml would keep it polymorphic then the following would be allowed,

log "hello"

and string_of_int "hello" is not well-typed.

So you have to keep both parameters required, e.g.,

let log to_string data = 
  print_endline (to_string data)

I would also suggest looking into the Format module and defining your own polymorphic function that uses format specification to define how data of different types are written, e.g.,

let log fmt = 
  Format.kasprintf print_endline fmt 

Substitute print_endline with our own logging facility. The log function could be used as printf, e.g.,

log "%s %d" "hello" 42
  • Related