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, 2004
    • 0 Attachment
      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, 2004
      • 0 Attachment
        > 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, 2004
        • 0 Attachment
          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@...
        • Christophe TROESTLER
          ... Hi Rich! I do not think you can initialize it then -- which make the optionality of the argument void of course. The better is then IMHO to define a
          Message 4 of 10 , Apr 8, 2004
          • 0 Attachment
            On Thu, 8 Apr 2004, Richard Jones <rich@...> 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?

            Hi Rich!

            I do not think you can initialize it then -- which make the
            optionality of the argument void of course. The better is then IMHO
            to define a shortcut for the default case:

            let plot_int = plot string_of_int

            ChriS
          • 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 5 of 10 , Apr 8, 2004
            • 0 Attachment
              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 6 of 10 , Apr 9, 2004
              • 0 Attachment
                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.