Function specification:
Write a function any_zeroes : int list -> bool that returns true if and only if the input list contains at least one 0
Code:
let any_zeroes l: int list =
List.exists 0 l
Error:
This expression has type int but an expression was expected of type
'a -> bool
I don't know why Ocaml is having an issue with the 0 when I marked l to be an int list. If anyone could help me fix the issue this would be greatly appreciated!
Thanks!
So, first of all, you didn't mark l as int list, the syntax:
let any_zeroes l: int list
Means that the any_zeroes is a function, that returns an int list. A correct way to annotate it, is the following:
let any_zeroes (l : int list) : bool
Second, the fact, that you mark something doesn't change the semantics of a program. It is a type constraint, that tells the type inference system, that you want this type to be unified to whatever you specified. If a type checker can't do this, it will bail out with an error. And type checker don't need your constraints, they are mostly added for readability. (I think they are also required by the course that you're taking).
Finally, the error points you not to the l (that, as you think, was annotated), but to the 0. And the message tells you, that List.exists function is accepting a function of type 'a -> bool as the first argument, but you're trying to feed it with 0 that has type int. So, the type system is trying to unify int and 'a list, and there is no such 'a that int = 'a list, so it doesn't type check. So you either need to pass a function, or to use List.mem as was suggested by Anton.
The type annotation let any_zeroes l: int list = ... means the type of any_zeroes l is int list; this is not what you mean here.
The correct type annotation related to your specification is:
let any_zeroes
: int list -> bool
= fun l -> List.exists 0 l
In the top level, it feedbacks:
= fun l -> List.exists 0 l;;
^
This expression has type int but an expression was expected of type
'a -> bool
Indeed, this expression fails to typecheck because of the type of List.exists:
# List.exists;;
- : ('a -> bool) -> 'a list -> bool = <fun>
The first argument is a predicate, which 0 is not.
A correct implementation is:
let any_zeroes
: int list -> bool
= let is_zero x = x = 0 in
fun l -> List.exists is_zero l
Related
If I have a function f defined as
f: 'a -> 'b -> c' -> d'
Does that mean it takes one argument? Or 3? And then it outputs one argument? How would I use or call such a function?
As Glennsl notes in the comments, it means both.
Very briefly, and by no means comprehensively, from an academic perspective, no function in OCaml takes more than one argument or returns more or less than one value. For instance, a function that takes a single argument and adds 1 to it.
fun x -> x + 1
We can give that function a name in one of two ways:
let inc = fun x -> x + 1
Or:
let inc x = x + 1
Either way, inc has the type int -> int which indicates that it takes an int and returns an int value.
Now, if we want to add two ints, well, functions only take one argument... But functions are first class things, which means a function can create and return another function.
let add =
fun x ->
fun y -> x + y
Now add is a function that takes an argument x and returns a function that takes an argument y and returns the sum of x and y.
We could use a similar method to define a function that adds three ints.
let add3 =
fun a ->
fun b ->
fun c -> a + b + c
The type of add would be int -> int -> int and add3 would have type int -> int -> int -> int.
Of course, OCaml is not purely an academic language, so there is convenience syntax for this.
let add3 a b c = a + b + c
Inferred types
In your question, you ask about a type 'a -> 'b -> 'c -> 'd``. The examples provided work with the concrete type int. OCaml uses type inferencing. The compiler/interpreter looks at the entire program to figure out at compile time what the types should be, without the programmer having to explicitly state them. In the examples I provided, the +operator only works on values of typeint, so the compiler _knows_ incwill have typeint -> int`.
However, if we defined an identity function:
let id x = x
There is nothing her to say what type x should have. In fact, it can be anything. But what can be determined, if that the function will have the same type for argument and return value. Since we can't put a concrete type on that, OCaml uses a placeholder type 'a.
If we created a function to build a tuple from two values:
let make_tuple x y = (x, y)
We get type 'a -> 'b -> 'a * 'b.
In conclusion
So when you ask about:
f: 'a -> 'b -> 'c -> 'd
This is a function f that takes three arguments of types 'a, 'b, and 'c and returns a value of type 'd.
Taking an exemple derived from RWOCaml :
utop # let divide ~first ~second = first / second;;
val divide : first:int -> second:int -> int = <fun>
utop # let apply_to_tuple_3 f (first,second) = f second first;;
val apply_to_tuple_3 : ('a -> 'b -> 'c) -> 'b * 'a -> 'c = <fun>
utop # apply_to_tuple_3 divide;;
Error: This expression has type first:int -> second:int -> int
but an expression was expected of type 'a -> 'b -> 'c
Does it make sense to not match the types here ?
apply_to_tuple_3 only makes use of the positional arguments, which certainly divide possesses.
Upon removing the names, the application is accepted
utop # let divide_an x y = divide x y;;
val divide_an : int -> int -> int = <fun>
utop # apply_to_tuple_3 divide_an;;
- : int * int -> int = <fun>
Is there any reason to reject the first call ?
Functions with labeled parameters have a type that depends on the labels and on the order that they appear. When calling such functions, there is flexibility in the order of arguments that you supply. And in fact you can omit the labels if you supply all of the arguments.
However, when passing such functions as values themselves, there is no such flexibility. You have only the one labeled type to work with.
This is covered on page 42 of Real World OCaml: Higher-order functions and labels.
(If you're asking why this is the case, I can only assume that type checking becomes difficult or impossible if you allow such flexibility.)
I've been learning OCaml recently and as of now it would seem an arrow is used by the compiler to signify what the next type would be. For instance, int -> int -> <fun> an integer which returns an integer, which returns a function.
However, I was wondering if I can use it natively in OCaml code. In addition, if anyone would happen to know the appropriate name for it. Thank you.
The operator is usually called type arrow where T1 -> T2 represents functions from type T1 to type T2. For instance, the type of + is int -> (int -> int) because it takes two integers and returns another one.
The way -> is defined, a function always takes one argument and returns only one element. A function with multiple parameters can be translated into a sequence of unary functions. We can interpret 1 + 2 as creating a +1 increment function (you can create it by evaluating (+) 1 in the OCaml command line) to the number 2. This technique is called Currying or Partial Evaluation.
Let's have a look at OCaml's output when evaluating a term :
# 1 + 2;;
- : int = 3
# (+) 1 ;;
- : int -> int = <fun>
The term1+2 is of type integer and has a value of 3 and the term (+) 1 is a function from integers to integers. But since the latter is a function, OCaml cannot print a single value. As a placeholder, it just prints <fun>, but the type is left of the =.
You can define your own functions with the fun keyword:
# (fun x -> x ^ "abc");;
- : bytes -> bytes = <fun>
This is the function which appends "abc" to a given string x. Let's take the syntax apart: fun x -> term means that we define a function with argument x and this x can now appear within term. Sometimes we would like to give function names, then we use the let construction:
# let append_abc = (fun x -> x ^ "abc") ;;
val append_abc : bytes -> bytes = <fun>
Because the let f = fun x -> ... is a bit cumbersome, you can also write:
let append_abc x = x ^ "abc" ;;
val append_abc : bytes -> bytes = <fun>
In any case, you can use your new function as follows:
# append_abc "now comes:" ;;
- : bytes = "now comes:abc"
The variable x is replaced by "now comes:" and we obtain the expression:
"now comes:" ^ "abc"
which evaluates to "now comes:abc".
#Charlie Parker asked about the arrow in type declarations. The statement
type 'a pp = Format.formatter -> 'a -> unit
introduces a synonym pp for the type Format.formatter -> 'a -> unit. The rule for the arrow there is the same as above: a function of type 'a pp takes a formatter, a value of arbitrary type 'a and returns () (the only value of unit type)
For example, the following function is of type Format.formatter -> int -> unit (the %d enforces the type variable 'a to become int):
utop # let pp_int fmt x = Format.fprintf fmt "abc %d" x;;
val pp_int : formatter -> int -> unit = <fun>
Unfortunately the toplevel does not infer int pp as a type so we don't immediately notice(*). We can still introduce a new variable with a type annotation that we can see what's going on:
utop # let x : int pp = pp_int ;;
val x : int pp = <fun>
utop # let y : string pp = pp_int ;;
Error: This expression has type formatter -> int -> unit
but an expression was expected of type
string pp = formatter -> string -> unit
Type int is not compatible with type string
The first declaration is fine because the type annotation agrees with the type inferred by OCaml. The second one is in conflict with the inferred type ('a' can not be both int and string at the same time).
Just a remark: type can also be used with records and algebraic data types to create new types (instead of synonyms). But the type arrow keeps its meaning as a function.
(*) Imagine having multiple synonymes, which one should the toplevel show? Therefore synonyms are usually expanded.
The given answer doesn't work for ADTs, GADTs, for that see: In OCaml, a variant declaring its tags with a colon
e.g.
type 'l generic_argument =
| GenArg : ('a, 'l) abstract_argument_type * 'a -> 'l generic_argument
I have anonymous function:
fun x -> x;;
- : 'a -> 'a = <fun>
As you may see, this function accepts argument of any type. I want to specify concrete type, say int.
I know that I can annotate functions with type specs, but do not know syntax for it.
It would be helpful to get some reference to this syntax and extend this example with such annotation.
Thanks.
# fun (x: int) -> x;;
- : int -> int = <fun>
#
The reason this works is that
Function parameters are specified as patterns.
One alternative for a patttern is of the form:
( pattern : typexpr )
Syntax for patterns is given in Section 6.6 of the OCaml manual.
The most general form is:
(fun x -> x : int -> int)
Since fun x -> x is a value by itself, it can be annotated with a type, as any other expression. Indeed, in this type annotation you can omit one of the int's, since the other can be inferred by a compiler:
(fun x -> x : int -> 'a)
or
(fun x -> x : 'a -> int)
all will result in:
- : int -> int = <fun>
This also demonstrates that 'a in type annotations has different meaning from 'a in signatures. In type annotation it stands for "I don't care, you decide". Thats why the proper name for type annotations is type constraining, thus you're not annotating your expression with type, but you're giving extra constraint for type inference system. In this example, you're saying to it: I have this expression, and please infer its type, giving it is a function that returns int.
Also, you can use _ instead of type variables, the same way as you can do this for a normal variables:
(fun x -> x : _ -> int)
The result will be the same.
Write an Ocaml function list_print : string list -> unit that prints all the strings in a list from left to right:
So Lets say I've got an Ocaml function list_print: string list -> unit that prints all the strings in a list from left to write. Now the correct solution is:
let list_print lst = List.fold_left (fun ( ) -> fun s -> print_string s) () lst;;
But When writing my solution, I wrote it as such:
let list_print lst = List.fold_left (fun s -> print_string s) () lst;;
But this gave me
Error: This expression has type unit but an expression was expected of type 'a -> string
Why is it that I need that first parameter fun() -> before the fun s? I'm still new to Ocaml so this type system is quite confusing to me
The purpose of fold_left (and fold_right) is to accumulate a value as you go along. The extra parameter is this accumulated value.
You can use List.iter for your problem. It doesn't accumulate a value.
You could think of List.iter as a version of List.fold_left that accumulates values of type unit. And, in fact, you could implement it that way:
let iter f = List.fold_left (fun () a -> f a) ()
The point (as always with unit) is that there's only one value of the type, so it represents cases where the value isn't interesting.
You want to use List.fold_left, that's fine, but you should start by reading the documentation for that function. The official documentation is quite short:
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
List.fold_left f a [b1; ...; bn] is f (... (f (f a b1) b2) ...) bn.
The first thing is the type of that function. The type is
('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
In other words, the function fold_left has three arguments and one result value. The first argument has type ('a -> 'b -> 'a). The second argument has type 'a. The third argument has type 'b list. The result value of the function has type 'a.
Now, in your case, you want to print the strings. So you do not actually need any result value, you need a side effect. However, in OCaml all functions must have a result value. So you use the empty value, (), which has type unit. Therefore, the type parameter 'a will be equal to unit in your case.
The type parameter 'b is string because you are required to work on the list of strings.
Therefore, in your case the function fold_left must have the type
(unit -> string -> unit) -> unit -> string list -> unit.
The first argument of fold_left must have the type unit->string->unit. In other words, it must be a function with two arguments, first argument is the empty value, i.e. (), the second argument a string. So the first argument to fold_left must be a function of this kind,
fun x y -> ...
where x must be of type unit and y of type string. Since x is going to be always equal to (), it is not necessary to write this argument as a variable x, instead we can simply write () or even the dummy argument _. (The syntax fun x -> fun y -> ... gives the same function as fun x y -> ....)
Now you can begin to figure out how fold_left works. Since this is obviously a homework question, I will leave this task to you.