I don't fully understand the type interface of List.comparewhich is:
('a -> 'a -> int) -> 'a list -> 'a list -> int
Are there any other use cases beside those examples:
List.compare (+) [1;3] [2;2];;
- : int = 3
List.compare (-) [1;3] [2;2];;
- : int = -1
List.compare (/) [1;3] [2;2];;
- : int = 1
List.compare ( * ) [1;3] [2;2];;
- : int = 2
This is quite a trivial question but the documentation is very minimalistic.
The basic idea is that you can lift a comparison function that works on some type into a comparison function that works on lists of the type. There are many ways to do this, but the obvious one is to use lexicographic order.
As #glennsl points out, only one of your examples makes any sense. You need to supply a comparison function for List.compare to lift. You can't supply an arbitrary function (if you want to get meanginful results).
Related
For my assignment, I need to return a list of lists given a tree.
For example, given this tree, we return the paths of the leaves, 0 being going to the left and 1 being going to the right. At the current moment, I believe my function makes sense; however, I have no idea how to make the lists into a list of lists. I believe an operation needs to be put where the question mark is; however I've looked online and I could not find anything. Is there an operation for this? Or do I have to create my own helper function? Thank you.
let rec dTree_path t =
match t with
| Leaf(x) -> []
| Node(x, lt, rt) -> [ 0 :: (dTree_path lt) ] ?? [1 :: (dTree_path rt)];;
I
When doing exercices where function types are well specified, it can be useful to write the specification explicitely in order to make the typechecker report issues as soon as possible. In this case, adding a type annotation yields a compiler error on 0::dTree_path lt
let rec dTree_path: 'any t -> int list list = fun x ->
match x with
| Leaf(x) -> []
| Node(x, lt, rt) -> [ 0 :: (dTree_path lt) ] …;;
Error: This expression has type int list list
but an expression was expected of type int list
Type int list is not compatible with type int
And indeed, the current issue with your function is that 0 :: (dTree_path lt) does not make sense with respect to your specification: dTree_path is a list of lists of ints (i.e. a list of paths), but you are appending an int element to this list.
Hint: What you want to do is to append 0 to each path of the list of path returned by dTree_path.
List.map is of type
- : ('a -> 'b) -> 'a list -> 'b list = <fun>
It's easy for me to understand the following code:
List.map (fun x -> x+1) [1;2;3;4];;
which adds 1 to each element of the list so it returns the following list :
- : int list = [2;3;4;5]
Now this is in an exercise where I'm asked to indicate the type of this :
List.map (fun p -> p 7) [ (fun n m -> n + m) ];;
I don't understand at all what it means to be honest.
What does p 7 mean ?
Why is there a function in the list ?
The type is
- : (int -> int) list = [<fun>]
But I can't understand why.
What does it mean when fun is between brackets ?
Thank you.
What does p 7 mean?
It means the application of function p to argument 7 .... You might spend some time reading the wikipage on λ-calculus (at least to learn about functional abstraction)
Read also about currying.
Why is there a function in the list ?
In Ocaml, functions are values, so you can have list of functions. If it was not a list of functions, you'll get a typing error. If you think more, you can understand what kind of functions are allowed.
What does it mean when fun is between brackets ?
The toplevel is not able to print functional values (implemented as closures). It shows them as <fun>. For a simpler example, pass fun x -> x+1;; (then try also fun y -> y;;) to your REPL.
(the rest of the exercise is left to the reader)
I'm just starting out with F*, by which I mean I've written a few lines along with the tutorial. So far it's really interesting and I'd like to keep learning.
The first thing I tried to do on my own was to write a type that represents a non-empty list. This was my attempt:
type nonEmptyList 'a = l : (list 'a) { l <> [] }
But I get the error
Failed to verify implicit argument: Subtyping check failed; expected
type (a#6468:Type{(hasEq a#0)}); got type Type
I know I'm on the right track though because, if I constrain my list type to containing strings, this does work:
type nonEmptyList = l : (list string) { l <> [] }
I'm assuming this means that l <> [] in the original example isn't valid because I haven't specified that 'a should support equality. The problem is that I cannot for the life of me figure out how to do that. I guess is has something to do with a higher kind called hasEq, but trying things such as:
type nonEmptyList 'a = l : (list 'a) { hasEq 'a /\ l <> [] }
hasn't gotten me anywhere. The tutorial doesn't cover hasEq and I can't find anything helpful in the examples in the GitHub repo so now I'm stuck.
You correctly identified the problem here. The type 'a that you used in the definition of nonEmptyList is left unspecified and therefore could not support equality. Your intuition is correct, you need to tell F* that 'a is a type that has equality, by adding a refinement on it:
To do that, you can write the following:
type nonEmptyList (a:Type{hasEq a}) = l : (list a) { l <> [] }
Note that the binder I used for the type is a and not 'a. It would cause a syntax error, it makes more sense because it isn't "any" type anymore.
Also, note that you can be even more precise and specify the universe of the type a as Type0 if needbe.
Your analysis is indeed correct, and the accepted answer gives the right solution in general.
For your concrete example, though, you don't need decidable equality on list elements: you can just use (list 'a){ ~ (List.isEmpty l) }.
For reference, here's the definition of isEmpty:
(** [isEmpty l] returns [true] if and only if [l] is empty *)
val isEmpty: list 'a -> Tot bool
let isEmpty l = match l with
| [] -> true
| _ -> false
I'm trying to understand better the OCaml type inference. I created this example:
let rec f t = match t with
| (l,r) -> (f l)+(f r)
| _ -> 1
and I want to apply it on any binary tuple (pair) with nested pairs, to obtain the total number of leafs. Example: f ((1,2),3)
The function f refuses to compile, because a contradiction in types at (f l): "This expression has type 'a but an expression was expected of type 'a * 'b".
Question: 'a being any type, could not also be a pair, or else be handled by the _ case? Is any method to walk tuples of arbitrary depth without converting them to other data structures, such as variants?
PS: In C++ I would solve this kind of problem by creating two template functions "f", one to handle tuples and one other types.
There is a way to do this, although I wouldn't recommend it to a new user due to the resulting complexities. You should get used to writing regular OCaml first.
That said, you can walk arbitrary types in a generic way by capturing the necessary structure as a GADT. For this simple problem it is quite easy:
type 'a ty =
| Pair : 'a ty * 'b ty -> ('a * 'b) ty
| Other : 'a ty
let rec count_leaves : type a . a -> a ty -> int =
fun a ty ->
match ty with
| Pair (ta, tb) -> count_leaves (fst a) ta + count_leaves (snd a) tb
| Other -> 1
Notice how the pattern matching on the a ty here corresponds to the pattern matching on values in your (poorly typed) example function.
More useful functions could be written with a more complete type representation, although the machinery becomes heavy and complicated once arbitrary tuples, records, sum types, etc have to be supported.
Any combination of tuples will have a value shape completely described by it's type (because there is no "choice" in the type structure) - hence the "number of leaves" question can be answered completely statically at compile-time. Once you have a function operating on such type - this function is fixed to operate on that specific type (and shape) only.
If you want to build a tree that can have different shapes (but same type - hence can be handled by same function) - you need to add variants to the mix, i.e. classic type 'a tree = Leaf of 'a | Node of 'a tree * 'a tree, or any other type that describes value with some dynamic "choice" of shape.
In OCaml, is there a way to refer to the cons operator by itself?
For example, I can use (+) and ( * ) as int -> int -> int functions, but I cannot use (::) as a 'a -> 'a list -> 'a list function, as the following example show:
# (+) 3 5;;
- : int = 8
# ( * ) 4 6;;
- : int = 24
# (::) 1 [2;3;4];;
Error: Syntax error: operator expected.
Is there a way to produce a result like (::) other than with fun x y -> x::y? And does anyone know why (::) wasn't implemented in OCaml?
Adding to the answer of #seanmcl,
Actually OCaml supports a prefix form of (::):
# (::)(1, []);;
- : int list = [1]
This is in the uncurried form, corresponding with the fact that all the OCaml variant constructors are not curried and cannot be partially applied. This is handled by a special parsing rule just for (::), which is why you got a rather strange error message Error: Syntax error: operator expected..
Update:
Upcoming OCaml 4.02 removes this parsing rule, therefore this is no longer available.
No. Cons (::) is a constructor, constructors can not be infix operators. The allowed infix symbols are here:
http://caml.inria.fr/pub/docs/manual-caml-light/node4.9.html
Some workarounds are (as you mention) the verbose
(fun x l -> x :: l)
and defining your own nontraditional infix cons
let (+:) x l = x :: l
As of Ocaml 4.03, you can now use cons (in the List module). That is, cons x xs is the same as x :: xs.
It's also possible to just define your own cons function:
let cons = fun a list -> a :: list