I want to accomplish something like this, but I can't quite get the syntax down.
type _ s = Var : 'a -> 'a s
type _ t =
| AA :('a -> 'a s) -> 'c t
| AB : ('a -> 'b s) -> 'c t
let apply_to x = function
| AA g -> g x
| AB g -> g x
Well, a type like 'a -> 'a s makes sense. You can see how the parameter is going to work. A type like ('a -> 'a s) -> 'c t doesn't make sense (to me). I don't see where the 'c type is supposed to come from. The same goes for 'a -> 'b s. I don't see where the 'b is supposed to come from. Types like this are usually associated with code that doesn't actually return at all (undefined code, code that raises an exception, etc.).
It's (very) possible there's a subtlety of GADTs that I don't understand, but maybe this will help at least a little.
Related
I am learning OCaml and so far I am having trouble to understand the concepts of types.
For example, if we have this following code:
# let func x = x;;
val func : 'a -> 'a = <fun>
From the official website, it tells me that 'a before the arrow is the unknown input type and 'a after the arrow is the output.
However, when I try to use function composition:
# let composition f x = f(x);;
val composition : ('a -> 'b) -> 'a -> 'b = <fun>
What ('a -> 'b) means?
Is 'a related to f and 'b related to x?
Another function composition that made me even more confused is:
# let composition2 f x = f(f(x));;
val composition2 : ('a -> 'a) -> 'a -> 'a = <fun>
I don't really understand why we don't have the 'b in this case.
Thank you in advance!
'a -> 'b is the type of a function that takes one argument of type 'a and returns a value of type 'b.
val composition : ('a -> 'b) -> 'a -> 'b means that composition is a function of two arguments:
the first one is of type ('a -> 'b), so a function as above
the second one is of type 'a
So, this function returns something of the same type as the return type of the first argument, 'b. Indeed, it takes a function and its argument and applies that function to the argument.
In the second case, you can work backwards from the inner call. Let's have a look at f(f(x))
x is something of any type 'b. We have no idea what kind of type this is yet.
Since we have f(x), f must be a function of type 'b -> 'c. It's 'b because we know it takes x as input, and x is of type 'b.
Thus, the type of composition2 is ('b -> 'c) -> 'b
Since we have f(f(x)), the type of f's argument must be the same as the type of its return value. So, 'b == 'c. Call that type 'a.
Since x is of type 'b, which is the same as 'a, x must be of type 'a.
Since f is of type 'b -> 'c, where 'b == 'a and 'c == 'a, f must be of type 'a -> 'a.
Thus, the type of composition2 is ('a -> 'a) -> 'a
Say I have the following
module IntPairs =
struct
type t = int * int
let compare (x0,y0) (x1,y1) =
match Stdlib.compare x0 x1 with
0 -> Stdlib.compare y0 y1
| c -> c
end
module PairsMap = Map.Make(IntPairs)
And I add a few elements:
let m = PairsMap.(empty |> add (1,1) 1 |> add (2,1) 1 |> add (1,2) |> add (2,2))
How would i use to_seq to print keys in ascending order?
I'm not to familiar with iterators in ocaml
This is more of a request for OCaml tutoring than a question about a specific problem in your code. It would generally be faster to read the documentation than to ask individual questions here on StackOverflow.
With that said, the Seq interface looks like this:
type 'a t = unit -> 'a node
and 'a node = Nil | Cons of 'a * 'a t
val empty : 'a t
val return : 'a -> 'a t
val map : ('a -> 'b) -> 'a t -> 'b t
val filter : ('a -> bool) -> 'a t -> 'a t
val filter_map : ('a -> 'b option) -> 'a t -> 'b t
val flat_map : ('a -> 'b t) -> 'a t -> 'b t
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
val iter : ('a -> unit) -> 'a t -> unit
As you can see, it offers many higher-order traversal functions. The one you would want to use is probably iter since you want to print the values rather than calculate with them. I.e., there is no return value for your desired usage.
However, you should note that the Map interface already has an iter function. As near as I can tell, there's no reason to convert to a sequence before doing your iteration. The Map.iter documentation says this:
The bindings are passed to f in increasing order with respect to the ordering over the type of the keys.
This is what you want, so Map.iter seems like it will do the trick.
PairsMap.iter my_print_function m
is it possible to write in sml/nj a function with the signature:
fn : 'a -> 'b
my initial purpose was to make a function with the signature:
fn: ( 'a -> 'b ) -> ( 'b -> 'a ) -> 'a -> 'b -> 'c
after many tries I got:
fn: ( 'a -> 'b ) -> ( 'b -> 'a ) -> 'a -> 'b -> 'c -> 'c
but I never succeeded to make as it was asked, and I realized that if it is possible for me to make a function from 'a to 'b I could find the solution.
There are only two possible implementations that give a 'a -> 'b function, and they're rarely useful:
Throwing an Exception
- fun foo a = raise Fail "error";
val foo = fn : 'a -> 'b
Looping Indefinitely
- fun bar a = bar a;
val bar = fn : 'a -> 'b
I have a hunch that some details have been lost in the translation, because the second type signature you've given doesn't make much sense.
is it possible to write in sml/nj a function with the signature:
fn : 'a -> 'b
Yes -- see this StackOverflow question (and make it a habit of checking for duplicates as you ask. ;-)
my initial purpose was to make a function with the signature:
foo : ('a -> 'b) -> ('b -> 'a) -> 'a -> 'b -> 'c
It could be like this:
exception Done
fun foo f g x y _ = (f x; g y; raise Done)
Or like this:
fun foo f g x y _ =
let fun inf () = inf ()
in f x; g y; inf () end
What makes these functions similar to functions with type 'a -> 'b is in fact the 'c part, since this type does not relate to the input types, just like 'b does not relate to 'a. The 'as and 'bs in foo actually serve a purpose and allow for some function application (f x, g y) even though these values cannot be a part of the result, since you have no type-safe way of transforming a value of type 'a or 'b into a value of type 'c.
I prepare for GATE Exam. one of the oldest question is unfamiliar with us. some experts please clarify this for us.
Which of the following can be a type for following ML function ?
my f(g, nil)=nil | f(g,x::xs)=(fn a ⇒ g(a,x))::f(g, xs);
1) (int *book → real) * bool list → (int → real) list
2) (bool *int → int) * real list → (bool → int) list
3) (int *int → real) * real list → (real → bool) list
4) (bool *real → int) * int list → (int → int) list
The Answer Sheets say (1) Is corrects. comments or short description for better understanding?
One of the first things you should do is rewrite the function definition yourself. This will force you to actually parse and understand it.
fun f (g, nil) = nil
| f (g, x :: xs) = (fn a => g (a, x)) :: f (g, xs);
So, f is a function, even the question says that, it must have type ... -> ...:
val f : ... -> ...
What does it receive? Let's take a look at the first pattern of the function:
fun f (g, nil) = nil
It's something of the form (a, b), which is a 2-tuple. The function's argument must be a tuple then:
val f : (... * ...) -> ...
Just by looking at the definition, we can't figure out what type g must have, but it uses nil for the second element of the tuple and nil is the empty list. That means the second component of the tuple must be a list of something:
val f : (... * ... list) -> ...
What else can we deduce? The return value is nil as well, which means that the function returns a list of something, unclear what that something is yet.
val f : (... * ... list) -> ... list
Ok, let's jump to the second pattern of the function definition now:
| f (g, x :: xs) = (fn a => g (a, x)) :: f (g, xs);
We don't find anything more about the type of the argument, we just got confirmation that the second element of the tuple must indeed be a list, because it uses the :: constructor.
Let's take a look at the body:
(fn a => g (a, x)) :: f (g, xs)
It looks like it's building a list, so it must return a list, which is in accordance with the return type we've sketched so far, i.e., ... list. Let's
try to figure out the type of elements.
It seems to add a function object as the head of the list built by recursively calling the function f, which we're currently investigating. So the elements of the list we're returning must be functions:
val f : (... * ... list) -> (... -> ...) list
What does that function do, though? It calls g with a 2-tuple argument. Now we can fill in some information about the first element of the 2-tuple f receives. It must be a function that receives a 2-tuple as well:
val f : (((... * ...) -> ...) * ... list) -> (... -> ...) list
Can we say anything about the a parameter received by the function literal added to the return list? Not really, just that it's passed to g. Can we tell anything about the type of x? Not really, just that it's passed to g. Moreover, is there any constraint between a and x? Doesn't look like it. So far, we can only tell that g's type must be looking something like this:
('a * 'b) -> 'c'
Where 'a, 'b and 'c are polymorphic types, i.e., any concrete type can satisfy them. You can view them as wholes. We can now fill in more of the type for the f function:
val f : ((('a * 'b) -> 'c) * ... list) -> (... -> ...) list
We can do more actually, we've already assign a type to the x variable, but that comes from the second argument of the 2-tuple received by f, so let's fill in that too:
val f : ((('a * 'b) -> 'c) * 'b list) -> (... -> ...) list
And we can even fill in the element type of the returned list, because we've already assigned types for that, too.
val f : ((('a * 'b) -> 'c) * 'b list) -> ('a -> 'c) list
We can remove some extra parenthesis from the type we came up with without changing the meaning, because of the type operator precedence rules:
val f : ('a * 'b -> 'c) * 'b list -> ('a -> 'c) list
Now, our function's type is complete. However, this type can't be found in the list of possible answers, so we'll have to see if any of them can be used instead of what we've determined. Why? Because our function type uses type variables, which can be filled in by concrete types. Let's take them one by one:
Choice 1
val f : ('a * 'b -> 'c) * 'b list -> ('a -> 'c) list
val f : (int * bool -> real) * bool list -> (int -> real) list
It looks like 'a could be int, 'b could be a bool (it's book in what you've pasted, but I'm assuming it was a typo) and 'c could be a real. All the replacements match these correspondences, so we declare that, yes, the first choice can be a possible type for the given function, even though not the most general. Let's take the second choice:
Choice 2
val f : ('a * 'b -> 'c) * 'b list -> ('a -> 'c) list
val f : (bool * int -> int) * real list -> (bool -> int) list
The type-variable to concrete -type correspondence table could be this:
'a -> bool
'b -> int
'c -> int
'b -> real
We can stop here because we can see that 'b was assigned to different types, so this function signature can't be assigned to the implementation we've been given.
Choice 3 and 4
They are similar to choice 2, but I'll let them as an exercise to the reader :)
Is there a way to have a recursive call but with different type parameters?
Here's an example which I think should compile, but doesn't.
let swap (a, b) = (b, a)
module Test : sig
val test : bool option ->
('a -> 'b -> 'c) * ('b -> 'a -> 'c)
-> 'a -> 'b -> 'c
end = struct
let rec test (b : bool option)
(f : ('a -> 'b -> 'c) * ('b -> 'a -> 'c))
(x : 'a) (y : 'b) : 'c =
match b with
| None -> (fst f) x y
| Some true -> (test None f x y)
| Some false -> (test None (swap f) y x)
end
The compiler insists that 'a and 'b must be the same type in test even though there's no reason for it. Is this a bug?
This is actually an very interesting question.
I didn't know the answer before, but by reading through the two answers before me, plus a bit research, I will try explain and answer below.
Basically, what you want to achieve is the signature like this
val test : bool option -> ('a -> 'b -> 'c) * ('b -> 'a -> 'c) -> 'a -> 'b -> 'c
First of all, I have to emphasise that trying to force the parameters to be different polymorphic types, i.e., use 'a, 'b, 'c etc, will not necessarily force OCaml compiler to think that the parameters must have different types.
for example, if you do
let f (x:'a) (y:'b) = x + y;;
It seems you are forcing x and y to be different types, but after compiling, it gives
val f : int -> int -> int = < fun >
Basically, OCaml will anyway do its type inference, and apply the conclusion if it is not just against the forced type.
You may think the 'a and 'b in let f (x:'a) (y:'b) = x + y;; to be maybe x and y will have different types and also possibly same types. So it is pointless to force types of parameters like that, right?
So, let's remove all the types forced on parameters and we get
let rec test b f x y =
match b with
| None -> (fst f) x y
| Some true -> test None f x y
| Some false -> test None (swap f) y x
The type of test will be given by OCaml like this:
val test : bool option -> ('a -> 'a -> 'b) * ('a -> 'a -> 'b) -> 'a ->
'a -> 'b = < fun >
So, basically, OCaml thinks x and y must have the same types, and c is not there because the next available type tag for OCaml to use is 'b.
Why x and y must have same types?
When OCaml meets let rec test b f x y, ok, it will think x has type of 'a and y has type of 'b'.
When OCaml meets | Some true -> test None f x y, no problem, the above type inference still stand because you are pass same x and y to test again.
The the funny part is when OCaml meets | Some false -> test None (swap f) y x. You are trying pass y and x (notice the order) to test. In order to let test work, x and y must have the same type, right?
Basically, above is what the counter side of polymorphism recursion #Jeffrey Scofield answered.
polymorphism recursion means, a function can have some parameters whose types can be changed during recursion, instead of stay constant.
OCaml by default of course only allow constant parameter types.
So how does rank 2 polymorphism work?
So how to solve it?
You need a for_all type 'a.. have a look at my question: In OCaml, what type definition is this: 'a. unit -> 'a.
If we use 'a. or 'a 'b. in type definition, then it means it is really for all types, real polymorphic types, and please, ocaml, do not narrow them down as long as it does not harm.
let rec test : 'a 'b. bool option -> ('a -> 'b -> 'c) * ('b -> 'a -> 'c) -> 'a -> 'b -> 'c =
fun b f x y ->
match b with
| None -> (fst f) x y
| Some true -> test None f x y
| Some false -> test None (swap f) y x
Above is the new version of test.
You force type with 'a 'b. for the function test and for 'a and 'b, ocaml will think they are really both polymorphic, and thus the parameter x and y can be accepted in both orders.
You're asking for polymorphic recursion, for which type inference is undecidable in the general case: Wikipedia on Polymorphic Recursion. So I don't think it's a bug.
I think there are ways to get what you want using rank-2 polymorphism.
I think it's a bug because if you create a new function (identical to the first one), then the type is correct:
# let rec t b f x y = match b with
| true -> (fst f) x y
| false -> u true (swap f) y x
and u b f x y = match b with
| true -> (fst f) x y
| false -> t true (swap f) y x;;
val t : bool -> ('a -> 'b -> 'c) * ('b -> 'a -> 'c) -> 'a -> 'b -> 'c = <fun>
val u : bool -> ('a -> 'b -> 'c) * ('b -> 'a -> 'c) -> 'a -> 'b -> 'c = <fun>
using OCaml 4.01.0:
module rec Test : sig
val test : bool option -> ('a -> 'b -> 'c) * ('b -> 'a -> 'c) -> 'a -> 'b -> 'c
end = struct
let rec test b f x y =
match b with
| None -> (fst f) x y
| Some true -> (Test.test None f x y)
| Some false -> (Test.test None (swap f) y x)
end;;
See the section on Recursive modules.
Small example as a test case:
let add_float_int x y = x +. (float y);;
let add_int_float x y = add_float_int y x;;
let adds = add_float_int, add_int_float;;
List.map (fun x -> Test.test x adds 10 10.) [None; Some true; Some false];;