Loading ...
Sorry, an error occurred while loading the content.
 

Re: "ocaml_beginners"::[] Polymorphic optional label argument, with default

Expand Messages
  • Martin Jambon
    ... Don t... It is written why somewhere in the documentation by I can t find where anymore. Here is my explanation: let f ?(opt = default) () = ... is
    Message 1 of 10 , Apr 8 9:03 AM
      On Thu, 8 Apr 2004, Richard Jones wrote:

      > I have a function defined:
      >
      > let plot ?(labels = string_of_int) graph =
      > (* ... *)
      >
      > The idea of the optional 'labels' argument is to specify a polymorphic
      > function 'a -> string which is used to print labels stored in the
      > 'graph' argument.
      >
      > The problem is that because string_of_int is obviously int -> string,
      > my function is typed as:
      >
      > plot : ?labels : (int -> string) -> (* ... int ... *) -> unit
      >
      > but I want it to be typed as:
      >
      > plot : ?labels : ('a -> string) -> (* ... 'a ... *) -> unit
      >
      > How to?

      Don't...
      It is written why somewhere in the documentation by I can't find
      where anymore.
      Here is my explanation:

      let f ?(opt = default) () = ...

      is replaced by the compiler by:

      let f option () =
      let opt =
      match option with
      None -> default
      | Some y -> y in
      ...

      and:

      f ~opt: z ()

      is replaced by:

      f (Some z) ()

      while:

      f ()

      is replaced by:

      f None ()


      In your problem, your printing function must be polymorphic, so the
      default parameter must be polymorphic too. What would happen if the
      labels have a type which is not int?

      What you can do is write a polymorphic function without specifying a
      default parameter, and then write a specialized version using you
      print_of_int default:

      let plot ?labels graph = ()
      let plot_int ?(labels = print_int) = plot ~labels

      So you keep the polymorphic version of plot, but you loose a little
      efficiency by constructing (Some thing) two times instead of one.
      Of course, it is probably insignificant in your example.

      Martin
    • Wheeler Ruml
      ... I had the same question a while back - this kind of idiom is pervasive in Common Lisp, which I used before coming to OCaml. The only solution I found
      Message 2 of 10 , Apr 8 9:52 AM
        > let plot ?(labels = string_of_int) graph =
        > (* ... *)
        >
        > my function is typed as:
        >
        > plot : ?labels : (int -> string) -> (* ... int ... *) -> unit
        >
        > but I want it to be typed as:
        >
        > plot : ?labels : ('a -> string) -> (* ... 'a ... *) -> unit

        I had the same question a while back - this kind of idiom is pervasive
        in Common Lisp, which I used before coming to OCaml. The only
        "solution" I found was to define two functions: one which takes a
        non-optional argument (the lack of the default preserves the
        polymorphism of the function) and another which omits that argument
        and calls the first function with the default filled in:

        let plot_with labels graph = .....

        let plot graph = plot_with string_of_int graph

        Please let me know if you find a better solution!

        Wheeler
      • Jeffrey J. Cook
        ... I ve fought with it, to no avail. My next best solution, partial application: type a graph = Foo of a let plot_with f g = match g with Foo b -
        Message 3 of 10 , Apr 8 12:27 PM
          On Thu, Apr 08, 2004 at 01:31:21PM +0100, Richard Jones wrote:
          >
          > I have a function defined:
          >
          > let plot ?(labels = string_of_int) graph =
          > (* ... *)
          >
          > The idea of the optional 'labels' argument is to specify a polymorphic
          > function 'a -> string which is used to print labels stored in the
          > 'graph' argument.
          >
          > The problem is that because string_of_int is obviously int -> string,
          > my function is typed as:
          >
          > plot : ?labels : (int -> string) -> (* ... int ... *) -> unit
          >
          > but I want it to be typed as:
          >
          > plot : ?labels : ('a -> string) -> (* ... 'a ... *) -> unit
          >
          > How to?

          I've fought with it, to no avail. My next best solution, partial application:

          type 'a graph = Foo of 'a

          let plot_with f g = match g with Foo b -> print_endline (f b)

          let plot = plot_with string_of_int

          Jeff

          --
          Jeffrey J. Cook
          Graduate Student, Electrical Engineering
          University of Illinois at Urbana-Champaign
          jjcook@...
        • Richard Jones
          It s possible what I meant was: val plot : a . (?labels : ( a - string) - (* ... a ... *)) - unit I m not sure of the exact syntax. It works when I leave
          Message 4 of 10 , Apr 8 3:53 PM
            It's possible what I meant was:

            val plot : 'a . (?labels : ('a -> string) -> (* ... 'a ... *)) -> unit

            I'm not sure of the exact syntax. It works when I leave out the
            default value for the optional argument. But I want that default
            argument in there.

            Rich.

            --
            Richard Jones. http://www.annexia.org/ http://www.j-london.com/
            Merjis Ltd. http://www.merjis.com/ - improving website return on investment
            MOD_CAML lets you run type-safe Objective CAML programs inside the Apache
            webserver. http://www.merjis.com/developers/mod_caml/
          • Frederic van der Plancke
            ... It seems theoretically impossible (in the current OCaml type system) for the following reason: if the default argument is in there, then the type you want
            Message 5 of 10 , Apr 9 1:05 AM
              Richard Jones wrote:
              >
              > It's possible what I meant was:
              >
              > val plot : 'a . (?labels : ('a -> string) -> (* ... 'a ... *)) -> unit
              >
              > I'm not sure of the exact syntax. It works when I leave out the
              > default value for the optional argument. But I want that default
              > argument in there.

              It seems theoretically impossible (in the current OCaml type system)
              for the following reason:

              if the default argument is in there, then the type you want
              for your function is:

              "....'a..... where 'a = int when ?labels is not provided"

              but there is no way to express such a type in OCaml. (AFAIK.)

              Frédéric.
            Your message has been successfully submitted and would be delivered to recipients shortly.