"Error: The function applied to this argument has type ..." when using named parameters
Asked Answered
H

2

17

I'm currently working through "Real Word OCaml", and one of the basic examples with named / labeled parameters doesn't seem to work (using utop 4.01.0):

let languages = ["OCaml"; "Perl"; "C"];;
List.map ~f:String.length languages;;

Produces:

Error: The function applied to this argument has type 'a list -> 'b list
This argument cannot be applied with label ~f

Whereas:

List.map String.length languages;;

Produces the expected output [5; 4; 1].

caml.inria.fr mentions that:

In the core language, as in most languages, arguments are anonymous.

Does this mean that I have to include some kind of external library to make this code work ?

EDIT Here's my ~/.ocamlinit file (as per the installation instructions for the book):

(* Added by OPAM. *)
let () =                
  try Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH")
  with Not_found -> ()
;;

#use "topfind"
#camlp4o
#thread
#require "core.top"
#require "core.syntax" 
Hymn answered 1/2, 2014 at 13:22 Comment(4)
I would expect the library needed to make this example work is Core (an “Industrial strength alternative to OCaml's standard library” as listed on ocaml.janestreet.com/ocaml-core/latest/doc ). Does the book not mention something about installing it first?Unconscionable
As far as I can tell, I've installed Core correctly; see my updated answer.Hymn
Did you put 'open Core.Std ;;' first ?Lydgate
@Lydgate That did the trick. If you add this as an answer, I'll gladly accept it.Hymn
H
14

As mentioned in @rafix's comment, this can be fixed by putting

open Core.Std ;;

first.

Hymn answered 13/6, 2014 at 7:12 Comment(1)
In newer versions, Core.Std is depracated. Use open Core;; instead.Teleology
V
2

The standard List.map method isn't defined with the label ~f. The type of List.map is ('a -> 'b) -> 'a list -> 'b list, but if you wanted to use the "~f" label, it would have to be "f:('a->'b) -> 'a list -> 'b list". If you wanted to define your own, you would have to define it as such:

 let rec myMap ~f l = match l with
 | [] -> []
 | h::t -> (f h) :: (myMap ~f t);;

 val myMap : f:('a -> 'b) -> 'a list -> 'b list = <fun>

and then you could call it like you wanted:

 myMap ~f:String.length languages

Cheers!

Venavenable answered 5/2, 2014 at 13:55 Comment(2)
+1 I don't want to define my own map function, but knowing how to use labeled parameters is certainly useful :-)Hymn
There is no lambda? why must use a label ?Jacqulynjactation

© 2022 - 2024 — McMap. All rights reserved.