This polymorphic function allows us to flip the order of the arguments of an arbitrary curried function:
# let flip f x y = f y x ;;
val flip : ('a -> 'b -> 'c) -> 'b -> 'a -> 'c
That is flip takes a function of type 'a -> 'b -> 'c and returns a function of type b -> 'a -> 'c. But I actually don't get it, why it is correct? how the order of a,b,c are determined by ? Pretty confused about it, can anyone explain for me, thank you.
Let's consider types of all given variables. If we have f : 'a -> 'b -> 'c, then from the code f y x in the function definition we have y : 'a and x : 'b. Also a return type of flip (i.e. a type of flip f x y) is a type of f y x, so 'c.
The function flip has three parameters, f, x, and y in this order. And it returns a value of f y x. Therefore the type of flip is:
flip : ('a -> 'b -> 'c) -> 'b -> 'a -> 'c
---------------- -- -- --
| | | |_ The type of the return value, (f y x)
| | |_ The type of y
| |_ The type of x
|_ The type of f
Perhaps this might help you. Instead of,
let flip f x y = f y x ;;
write the equivalent definition,
let flip f = fun x y -> f y x;;
now look at the type,
val flip : ('a -> 'b -> 'c) -> 'b -> 'a -> 'c
it's the same as this, with parenthesis,
val flip : ('a -> 'b -> 'c) -> ('b -> 'a -> 'c)
the function flip takes a function f of type 'a -> 'b -> 'c and returns the function \fun x y -> f y x of type 'b -> 'a -> 'c.
Related
I found myself wanting a way to do some codegen around some large variant types in my code, and I found ppx_variants_conv (https://github.com/janestreet/ppx_variants_conv)
The make_matcher method sounds potentially useful to me, but there are no docs and tbh I am struggling to read the example signature:
val make_matcher :
a:(('a -> 'a t) Variant.t -> 'b -> ('c -> 'd) * 'e)
-> b:((char -> 'f t) Variant.t -> 'e -> (char -> 'd) * 'g)
-> c:('h t Variant.t -> 'g -> (unit -> 'd) * 'i)
-> d:((int -> int -> 'j t) Variant.t -> 'i -> (int -> int -> 'd) * 'k)
-> 'b
-> ('c t -> 'd) * 'k
a b c and d labelled arguments correspond to the cases of the variant and the first part of each signature corresponds to the constructor for each case... I get a bit lost after that 🤔
and it seems a odd to me that 'b 'c 'd and 'k appear in the latter part of the signature but not 'e 'f 'g 'h 'i 'j
In the make_matcher function each labeled argument takes a function of two arguments that has a general form, fun v x -> f, y, where v is the first-class variant that represents the corresponding constructor, x is the value that is folded over all matchers-generating functions. The function returns a pair, in which the first constituent, the function f, is actually the matcher that will be called if that variant matches and some value y that will be passed to the next matcher-generating function.
Let's do some examples to illustrate this. First, let's define some simple matcher, e.g.,
type 'a t =
| A of 'a
| B of char
| C
| D of int * int
[##deriving variants]
let matcher init = Variants.make_matcher
~a:(fun v (x1 : char) ->
(fun x -> x+1),Char.code x1)
~b:(fun v (x2 : int) ->
(fun c -> Char.code c),float x2)
~c:(fun v (x3 : float) ->
(fun () -> 0), string_of_float x3)
~d:(fun v (x4 : string) ->
(fun x y -> x + y),[x4])
init
and here's how we can use, it,
# let f,s = matcher '*';;
val f : int t -> int = <fun>
val s : Base.string list = ["42."]
# f (A 10);;
- : int = 11
# f (B '*');;
- : int = 42
# f C;;
- : int = 0
# f (D (1,2));;
- : int = 3
To be honest, I don't know the purpose of the extra parameter that is passed to each matcher-generating function1. Probably, the idea is that depending on the initial parameter we could generate different matchers. But if you don't need this, then just pass () to it and/or define your own simplified matcher that ignores this additional information, e.g.,
let make_simple_matcher ~a ~b ~c ~d =
fst ##Variants.make_matcher
~a:(fun _ _ -> a,())
~b:(fun _ _ -> b,())
~c:(fun _ _ -> c,())
~d:(fun _ _ -> d,())
()
The make_simple_matcher function has an expected type,
a:('a -> 'b) ->
b:(char -> 'b) ->
c:(unit -> 'b) ->
d:(int -> int -> 'b) ->
'a t -> 'b
1) looking into the guts of the code that generates this function doesn't help a lot, as they use the generic name acc for this parameter, which is not very helpful.
let app = fun f -> fun x -> f (x);;
(*val app : ('a -> 'b) -> 'a -> 'b = <fun>*)
let app = fun f -> fun x -> x (f+1);;
(*val app : int -> (int -> 'a) -> 'a = <fun>*)
let app = fun f -> fun x -> x (f);;
(*val app : 'a -> ('a -> 'b) -> 'b = <fun>*)
let app2 = fun f -> fun g -> fun x -> g ( f x );;
(*val app2 : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c = <fun>*)
let app2 = fun f -> fun g -> fun x -> f (g x );;
(*val app2 : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>*)
let app2 = fun f -> fun g -> fun x -> g (f x+1);;
(*val app2 : ('a -> int) -> (int -> 'b) -> 'a -> 'b = <fun>*)
let app2 = fun f -> fun g -> fun x -> f (g x+1 );;
(*val app2 : (int -> 'a) -> ('b -> int) -> 'b -> 'a = <fun>*)
let app3 = fun f -> fun g -> fun x -> g f x+1 ;;
(*val app3 : 'a -> ('a -> 'b -> int) -> 'b -> int = <fun>*)
How do I know what happens in the val line without tapping enter on the let app line.
To be more specific I dont understand the relation between let and val.
For example, for the first one:
let app = fun f -> fun x -> f (x);;
(*val app : ('a -> 'b) -> 'a -> 'b = <fun>*)
What I see is that the first x takes the name 'a
and after it goes to the f which takes the name 'b
and after it goes to the fun x which is 'a again
and after it goes to the fun y which is 'b again.
But it is clearly not the case with other functions.
How do I know how they are related?
Someone has put the types of these functions in comments below the actual code. Comments in OCaml are surrounded by (* and *).
These type signatures are identical to what you'd see in an OCaml toplevel. You enter an expression, followed by ;;, this code is evaluated, and you're shown the resulting value.
Consider:
# 4 + 5;;
- : int = 9
# let a = 4 + 5;;
val a : int = 9
#
The val only shows up if I've introduced a name for the value. In either case we're shown the type of the resulting value and the value itself.
When you see things like 'a and 'b you're seeing type variables that OCaml infers when it can't infer a specific type. This very recent question is worth reading.
let is used to create name-bindings(alternatively named definitions if you would like to call it), where a binding will have a name and will be bound to an expression, which when evaluated will produce a value.
fun is used to create/define anonymous function, Anonymous functions are function expression which means an expression of type function, which when evaluated given its arguments will produce a value, and this function expression can itself be passed around like any other regular value.. and this function expression is bound using a let.
For example
let app = fun f -> fun x -> x (f+1)
In this case, we are defining a name app which will be bound to the expression produced by fun on the right. The fun takes a parameter f whose type will be inferred by the compiler once it is done processing the body of that function expression. The same applies to the next function expression which takes a parameter named x.
By looking at the right-most expression, which is responsible for generating the reduced value, we see f getting applied to the operator + and so f will receive it's type from that expression. And then x (...) entails a function application, so the x will receive it's type from that expression.
And we can go on applying the same to every expression cited in the question.
Essentially, let bindings, lambda expressions, type inference, function application, function expression etc... are some of the topics one should get acquainted with to understand what's going on.
Hello I am getting ready for my finals and there is always ml type inference on the exams .
i.e. we are asked to write the type of a function like this one :
fun ugh x y z = x z (y z);
val ugh = fn : ('a -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'c
or
fun doh x y z = z (x y ) (y + 1);
val doh = fn : (int -> 'a) -> int -> ('a -> int -> 'b) -> 'b
However all the ways I am trying to infer the type I always get it wrong .
Although there are examples online there are no examples for functions like that .
Is there a way to make up the type following some guidelines ?
The guidelines would be best if applied to the first example .
Yes, there are several examples of type inference by hand on StackOverflow: 1, 2, 3, 4, 5, ...
To infer the type of fun ugh x y z = x z (y z), you could start by saying that
val ugh : 'a -> 'b -> 'c -> 'd
since it takes three curried arguments. You can also see that x : 'a is a function of two curried parameters and that y : 'b is a function of one parameter, and that 'd should be expressed entirely in terms of 'a, 'b and 'c.
So for the type of y, set 'b = 'c -> 'e, since it takes z : 'c as input and returns something of a type that we haven't gotten to yet.
And for the type of x, set 'a = 'c -> 'e -> 'f, since it takes z : 'c and the output of y as input and returns something of a type that we haven't gotten to yet.
Replacing those, adding parentheses as needed, you get
val ugh : ('c -> 'e -> 'f) -> ('c -> 'e) -> 'c -> 'f
At that point you might want to rename them so you get
val ugh : ('a -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'c
but you don't really have to.
The only things I had to think about here was the fact that the type of x depends on the type of y, so I wanted to determine that first.
To infer the type of fun doh x y z = z (x y) (y + 1), you could similarly start by saying that
val doh : 'a -> 'b -> 'c -> 'd
since it also takes three curried arguments. Most easily you can set 'b = int, and similar to the first example, you can set 'a = int -> 'e and then 'c = 'e -> int -> 'd.
Replacing those, adding parentheses as needed, you get
val doh : (int -> 'e) -> int -> ('e -> int -> 'd) -> 'd
or after a little renaming
val doh : (int -> 'a) -> int -> ('a -> int -> 'b) -> 'b
As a pass-time, I'm trying to implement all kinds of problems that were presented in a course (concerned with Lambda Calculus and various programming concepts) I took at the university. So, I'm trying to implement Church numerals and associated operators in OCaml (also as an exercise in OCaml).
This is the code so far:
let church_to_int n =
n (fun x -> x + 1) 0;;
let succ n s z =
s (n s z)
let zero = fun s z -> z
let int_to_church i =
let rec compounder i cont =
match i with
| 0 -> cont zero
| _ -> compounder (i - 1) (fun res -> cont (succ res))
in
compounder i (fun x -> x)
let add a b = (b succ) a
let mul a b = (b (add a)) zero
So, it seems to work, but then it breaks down. Let's consider these definitions:
let three = int_to_church 3
let four = int_to_church 4
church_to_int (add three four) // evaluates to 7
church_to_int (add four three) // throws type error - see later
I get that the error thrown has to do with the type polymorphism of the Church numerals when they're defined (see SO question), and then it's resolved after the closures are invoked once. However, I don't seem to understand why the type inconsistency error is thrown in this case:
let three = int_to_church 3
let four = int_to_church 4
church_to_int (mul three four) // throws type error - see later
Any thoughts?
The specific errors:
1.
Error: This expression has type (int -> int) -> int -> int but an expression was expected of type ((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
((((int -> int) -> int -> int) -> (int -> int) -> int -> int) ->
((int -> int) -> int -> int) -> (int -> int) -> int -> int) ->
'd
Type int is not compatible with type ('a -> 'b) -> 'c -> 'a
2.
Error: This expression has type ((((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) -> (('d -> 'd) -> 'd -> 'd) -> 'e) ->
((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e) ->
(((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e) ->
((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e
but an expression was expected of type
((((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e) ->
'e) ->
('f -> 'g -> 'g) -> 'h
The type variable 'e occurs inside
((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e
Well i was a bit rusty with lambda-calculus, but after few discussions with some wise old men, i came to this answer : YES, writing that way, OCaml's type system do not allow the writing of Church numerals.
The real problem here is with your addition term :
let add a b = b succ a
wich has the following type
(((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) -> 'd -> 'e) -> 'd -> 'e
Where the arguments of add have not the same type. This is a bit sad since we naively expect the addition to be commutative.
You can easily verify this when writing :
let double a = add a a (* produces type error - the type variable occurs ... *)
This error means that you're trying to unify one type with a "bigger" type i.e that contains it (ex: unifying 'a with 'a -> 'a). OCaml does not allow that (unless if you set the -rectypes option wich allows cyclic types).
To understand better what's going on, let's add type annotations to help the typer (i'll change a bit your notations for sake of clarity):
type 'a church = ('a -> 'a) -> 'a -> 'a
let zero : 'a church = fun f x -> x
let succ n : 'a church = fun f x -> f (n f x)
Now let's go back to the add term and annotate it a bit to see what the typer has to say:
let add (a:'a church) b = a succ b (* we only annotate "a" to let the typer infer the rest *)
This produces a very odd type :
'a church church -> 'a church -> 'a church
That gets interesting: why is the first arg typed as an 'a church church?
The answer is the following : Here, a church integer is a value that takes a moving function of type 'a -> 'a (a self-map in mlahematics) that can browse a space, and an starting point ('a) that belongs to that space.
Here, if we specify that the parameter a has type 'a church, than 'a represent the space in which we can move.
Since succ, the moving function of a, operates over the church, than 'a here is it self an 'a church, thus making the parameter a an 'a church church.
This is not at all the type we wanted at the begining ... but that justifies why the type system do not allow your values three and four as both 1st and snd argument of add.
One solution can be to write add in a different way :
let add a b f x = a f (b f x)
Here, both a and b have the same moving function, and thus the same type, but you do not enjoy anymore the beautiful writing with the partial application ...
An other solution which makes you keep this beautiful writing would be to use universal types, that allow a larger kind of polymorphism:
type nat = {f:'a.('a -> 'a) -> 'a -> 'a}
(* this means “for all types ‘a” *)
let zero : nat = {
f=fun f x -> x
}
let succ n : nat = {
f= fun f x -> f (n.f f x)
}
let add (a:nat) (b:nat) = a.f succ b
let double a = add a a (* Now this has a correct type *)
let nat_to_int n =
n.f (fun x -> x + 1) 0;;
let nat_four = succ (succ (succ (succ zero)))
let eight_i = double nat_four |> nat_to_int //returns 8
But this solution is a bit more verbose than your initial one.
Hope it was clear.
If you look at the type of three, you get that:
val three : ('_a -> '_a) -> '_a -> '_a = <fun>
This is simply the value restriction at work. The value restriction is well explained here: https://realworldocaml.org/v1/en/html/imperative-programming-1.html#side-effects-and-weak-polymorphism
To solve it, In this case you can simply eta-expand the function:
let three x = int_to_church 3 x ;;
val three : ('a -> 'a) -> 'a -> 'a = <fun>
I have a parameterized type that recursively uses itself but with a type parameter specialized and when I implement a generic operator, the type of that operator is bound too tightly because of the case that handles the specialized sub-tree. The first code sample shows the problem, and the second shows a workaround that I'd rather not use because the real code has quite a few more cases so duplicating code this way is a maintenance hazard.
Here's a minimal test case that shows the problem:
module Op1 = struct
type 'a t = A | B (* 'a is unused but it and the _ below satisfy a sig *)
let map _ x = match x with
| A -> A
| B -> B
end
module type SIG = sig
type ('a, 'b) t =
| Leaf of 'a * 'b
(* Here a generic ('a, 'b) t contains a specialized ('a, 'a Op1.t) t. *)
| Inner of 'a * ('a, 'a Op1.t) t * ('a, 'b) t
val map : ('a -> 'b) -> ('a_t -> 'b_t) -> ('a, 'a_t) t -> ('b, 'b_t) t
end
module Impl : SIG = struct
type ('a, 'b) t =
| Leaf of 'a * 'b
| Inner of 'a * ('a, 'a Op1.t) t * ('a, 'b) t
(* Fails signature check:
Values do not match:
val map :
('a -> 'b) ->
('a Op1.t -> 'b Op1.t) -> ('a, 'a Op1.t) t -> ('b, 'b Op1.t) t
is not included in
val map :
('a -> 'b) -> ('a_t -> 'b_t) -> ('a, 'a_t) t -> ('b, 'b_t) t
*)
let rec map f g n = match n with
| Leaf (a, b) -> Leaf (f a, g b)
(* possibly because rec call is applied to specialized sub-tree *)
| Inner (a, x, y) -> Inner (f a, map f (Op1.map f) x, map f g y)
end
This modified version of Impl.map fixed the problem but introduces a maintenance hazard.
let rec map f g n = match n with
| Leaf (a, b) -> Leaf (f a, g b)
| Inner (a, x, y) -> Inner (f a, map_spec f x, map f g y)
and map_spec f n = match n with
| Leaf (a, b) -> Leaf (f a, Op1.map f b)
| Inner (a, x, y) -> Inner (f a, map_spec f x, map_spec f y)
Is there any way to get this to work without duplicating the body of let rec map?
Applying gasche's solution yields the following working code:
let rec map
: 'a 'b 'c 'd . ('a -> 'b) -> ('c -> 'd) -> ('a, 'c) t -> ('b, 'd) t
= fun f g n -> match n with
| Leaf (a, b) -> Leaf (f a, g b)
| Inner (a, x, y) -> Inner (f a, map f (Op1.map f) x, map f g y)
This style of recursion in datatype definitions is called "non-regular": the recursive type 'a t is reused at an instance foo t where foo is different from the single variable 'a used in the definition. Another well-known example is the type of full binary trees (with exactly 2^n leaves):
type 'a full_tree =
| Leaf of 'a
| Node of ('a * 'a) full_tree
Recursive functions that operate these datatypes typically suffer from the monomorphic recursion restriction of languages with type inference. When you do type inference you have to make a guess at what the type of a recursive function may be, before type-checking its body (as it may be use inside). ML languages refine this guess by unification/inference, but only monomorphic types may be inferred. If your function makes polymorphic uses of itself (it calls itself recursively on a different type that what it took as input), this cannot be inferred (it is undecidable in the general case).
let rec depth = function
| Leaf _ -> 1
| Node t -> 1 + depth t
^
Error: This expression has type ('a * 'a) full_tree
but an expression was expected of type 'a full_tree
Since 3.12, OCaml allows to use an explicit polymorphic annotation of
the form 'a 'b . foo, meaning forall 'a 'b. foo:
let rec depth : 'a . 'a full_tree -> int = function
| Leaf _ -> 1
| Node t -> 1 + depth t
You could do the same in your example. However, I wasn't able to
compile the type after using the annotation you have in your module
signature, as it appear to be wrong (the 'a_t are just weird). Here
is what I used to make it work:
let rec map : 'a 'b . ('a -> 'b) -> ('a Op1.t -> 'b Op1.t) ->
('a, 'a Op1.t) t -> ('b, 'b Op1.t) t
= fun f g n -> match n with
| Leaf (a, b) -> Leaf (f a, g b)
| Inner (a, x, y) -> Inner (f a, map f (Op1.map f) x, map f g y)