Type of statement given a function with polymorphic type ocaml - ocaml

If I have a function with polymorphic type
f : 'a -> 'a * 'a -> ('a * 'a) list
I also have:
type test = float * float
What will be the type of the following statement?
let ab: test = (0., 0.) in fun x -> f x test
I'm confused with the x here, is it the name of fun or it's simply input of fun, cause the input for f should be 'a, but not 'a -> 'a.
Right now I'm thinking if the type of the statement should be:
'a -> test * test -> (test * test) list

You have a good tool to try all your hypothesis on OCaml type system at hand: the OCaml REPL.
Currently,
type test = float * float
exception Hole
let f: 'a -> ('a * 'a) -> ('a * 'a) list = fun x -> fun y -> raise Hole
let mysterious =
let ab: test = (0., 0.) in fun x -> f x cd
yields
Error: Unbound value cd
Thus the mysterious expression doesn't have a type because it is not well defined.
EDIT: After correcting the typo,
let mysterious =
let ab: test = (0., 0.) in fun x -> f x ab
will yield the correct type. Then you should compare this type with the one you obtained by applying the type inference rule by hand to catch your mistake.
However, without knowing how you concluded that the type of mysterious was 'a -> test * test -> (test * test) list it is hard to pinpoint the first mistake in your reasoning.

There seems to be some basic syntax confusion regarding functions.
fun x -> ...
You've introduced an anonymous function that takes an argument named x and returns some other value.
If you wish to give that function a name, you can bind a name to it.
let foo = fun x -> ...
Note that the following is equivalent.
let foo x = ...

Related

What does f: 'a -> b' -> c' -> d' mean in ocaml?

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.

Parametrically polymorphic modules

Here is a simple OCaml module type for a monad:
module type Monad = sig
type 'a t
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
end
I can instantiate this with any particular monad, such as the reader monad for some type r:
module Reader_monad : Monad = struct
type 'a t = r -> 'a
let return a = fun _ -> a
let bind o f = fun x -> f (o x) x
end
And I can parametrize it over the type r by using a functor:
module type Readable = sig type r end
module Reader (R : Readable) : Monad = struct
type 'a t = R.r -> 'a
let return a = fun _ -> a
let bind o f = fun x -> f (o x) x
end
However, the latter approach requires that I instantiate different instances of the functor for different types r. Is there any way to define a "parametrically polymorphic" module of type Monad that would give parametrically polymorphic functions like return : 'a -> ('r -> 'a)?
I think can get more or less what I want with a separate module type for "families of monads":
module type Monad_family = sig
type ('c, 'a) t
val return : 'a -> ('c, 'a) t
val bind : ('c, 'a) t -> ('a -> ('c, 'b) t) -> ('c, 'b) t
end
module Reader_family : Monad_family = struct
type ('c, 'a) t = 'c -> 'a
let return a = fun _ -> a
let bind o f = fun x -> f (o x) x
end
But if I have a substantial library of general facts about monads, this would require modifying it everywhere manually to use families. And then some monads are parametrized by a pair of types (although I suppose that could be encoded by a product type), etc. So I would rather avoid having to do it this way.
If this isn't directly possible, is there at least a way to instantiate the module Reader locally inside a parametrically polymorphic function? I thought I might be able to do this with first-class modules, but my naive attempt
let module M = Reader(val (module struct type r = int end) : Readable) in M.return "hello";;
produces the error message
Error: This expression has type string M.t
but an expression was expected of type 'a
The type constructor M.t would escape its scope
which I don't understand. Isn't the type M.t equal to int -> string?
I think this is the same issue as The type constructor "..." would escape its scope when using first class modules, where the module M doesn't live long enough. If you instead wrote
# module M = Reader(struct type r = int end);;
# M.return "hello";;
- : string M.t = <fun>
then this would work fine.
Separately, the Reader functor loses some type equalities that you might want. You can restore them by defining it as such:
module Reader (R : Readable) : Monad with type 'a t = R.r -> 'a = struct
type 'a t = R.r -> 'a
let return a = fun _ -> a
let bind o f = fun x -> f (o x) x
end

How to lift a value into a monad

I'm trying to use the Writer monad in OCaml.
module Writer : Monad = struct
type 'a t = 'a * string
let return x = (x, "")
let (>>=) m f =
let (x, s1) = m in
let (y, s2) = f x in
(y, s1 ^ s2)
end
The statement below works.
Writer.(>>=) (Writer.return 2) (fun x -> Writer.return 1);;
But the statement below does not.
Writer.(>>=) (Writer.return 2) (fun x -> (x, "inc"));;
Error: This expression has type 'a * 'b but an expression was expected of type
'c Writer.t
I tried
Writer.(>>=) (Writer.return 2) (fun x -> ((x, "inc") : int Writer.t))
Error: This expression has type 'a * 'b but an expression was expected of type
int Writer.t
What am I doing wrong here? How can I lift a value into a monad in OCaml?
As mentioned, the code works with:
Writer.(>>=) (Writer.return 2) (fun x -> Writer.return 1);;
This is because the signature that describes the monad, here Monad, probably has this form:
module type Monad = sig
type 'a t
val return : 'a -> 'a t
val ( >>= ) : 'a t -> ('a -> 'b t) -> 'b t
end
As the concrete implementation of 'a t is not yet known (the type module potentially serving several implementations), 'a t is "abstract".
One approach would therefore be to "de-abstract" it.
This is possible by reflecting in the signature of the Writer module that we want to implement the Monad module while not making the type 'a t abstract, in this way:
module Writer : Monad with type 'a t = 'a * string = struct
type 'a t = 'a * string
let return x = (x, "")
let (>>=) m f =
let (x, s1) = m in
let (y, s2) = f x in
(y, s1 ^ s2)
end
In this way, the type `'a t' will no longer be abstract.
As a side note, I personally think it's not particularly bad that the Writer (or Reader, or State) type is abstract. The fact that it's a couple seems to me to be an implementation detail, some piping that doesn't need to be leaked.
A more fundamental issue is that the signature constraint
module Any_monad : Monad
is almost always a mistake in OCaml.
Signature constraints remove information that stick out of the signature. Thus, after the constraint, Any_monad could be replaced by any other monads fulfilling the monad signature (if we temporarily exclude side-effectful monads). For instance, you could replace the Writer monad with this very useful monad:
module Nil = struct
type 'a t = unit
let bind x f = ()
let (>>=) = bind
let return x = ()
end
In other words, an useful monad needs to have functions that are not part of the monad interface. In the case of the Writer monad that would be a write function:
module Writer: sig
include Monad
val write: string -> unit t
val read: 'a t -> string
end = struct
...
end
Notice that we have extended the signature before using it as a constraint.
Once, those functions available, your original code can be rewritten as:
Writer.(return 2 >>= fun x -> write "inc" >>= fun () -> return x)
You're constraining your monad implementation to be a Monad but, in fact, you want its type to have the Writer signature. To put it in other words, you're upcasting your implementation and forgetting that it also have to implement operations specific to the Writer monad. Obviously, this renders your Writer monad useless as you can't write anything.
To get it fixed, we first need to define the Writer module type, a common definition might look something like this,
module type Writer = sig
type state
val write : state -> unit t
val read : 'a t -> state t
val listen : 'a t -> ('a * state) t
val exec : unit t -> state
include Monad with type 'a t := 'a t
end
Now you need to implement the newly added operations with the state type set to string and then you will be able to use your Writer monad without breaking its abstraction,
module Writer : Writer with type state = string = struct
type state = string
type 'a t = 'a * string
let return x = (x, "")
let (>>=) m f =
let (x, s1) = m in
let (y, s2) = f x in
(y, s1 ^ s2)
let write x = (),x
let read (_,x) = x
let listen (x,s) = ((x,s),s)
let exec (_,x) = x
end
There are few libraries that implement monads in OCaml, so you don't need to re-invent it by your own. You can try the monads library that we develop at CMU. It could be installed with
opam install monads

behavior explanation for higher order functions and labeled argument in OCaml

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.)

A strange example of typing in Ocaml

it is quite strange that this ocaml snippet is well typed by the toplevel. Look at the structure, if g is of type int->int as shown in the toplevel, the h x = g x part of the structure would not be able to get type-unified. So can any one clarify a bit?
module Mymodule : sig
val h:int ->int
val g: string-> string
end = struct
let g x = x
let h x = g x
end
This is the topelevel's response:
module Mymodule : sig val h : int -> int val g : string -> string end
The important thing to understand here is that OCaml performs type inference in a compositional manner, i.e., it will first infer type of struct ... end and only then it will match the inferred types against sig ... end to verify that the structure really does implement the signature.
For example, if you write
module Monkey : sig val f : int -> int end =
struct
let f x = x
end
then OCaml will be happy, as it will see that f has a polymorphic type 'a -> 'a which can be specialized to the required type int -> int. Because the sig ... end makes Monkey opaque, i.e., the signature hides the implementation, it will tell you that f has type int -> int, even though the actual implementation has a polymorphic type.
In your particular case OCaml first infers that g has type 'a -> 'a, and then that the type of h is 'a -> 'a as well. So it concludes that the structure has the type
sig val g : 'a -> 'a val h : 'a -> 'a end
Next, the signature is matched against the given one. Because a function of type 'a -> 'a can be specialized to int -> int as well as string -> string OCaml concludes that all is well. Of course, the whole point of using sig ... end is to make the structure opaque (the implementation is hidden), which is why the toplevel does not expose the polymorphic type of g and h.
Here is another example which shows how OCaml works:
module Cow =
struct
let f x = x
let g x = f [x]
let a = f "hi"
end
module Bull : sig
val f : int -> int
val g : 'b * 'c -> ('b * 'c) list
val a : string
end = Cow
The response is
module Cow :
sig
val f : 'a -> 'a
val g : 'a -> 'a list
val a : string
end
module Bull :
sig
val f : int -> int
val g : 'a * 'b -> ('a * 'b) list
val a : string end
end
I'd say that the string -> string typing isn't applied to g until it's exported
from the module. Inside the module (since you don't give it a type) it has the type
'a -> 'a. (Disclaimer: I'm not a module expert, trying to learn though.)