I have:
- fun F p q = p q;
val F = fn : ('a -> 'b) -> 'a -> 'b
I know how to use it, for example by first having fun square x = x*x and then invoking F Sq 3. However, I don't quite understand the function expression in the second line. Can someone help paraphrase it in English and indicating which parameter is 'a and which is 'b'.
F here is a so called higher-order function which has two arguments:
p which has type 'a -> 'b (so it's a function!)
q which has type 'a
F (if applied first to an 'a -> 'b and then to an 'a produces an `b
The second line just tells you exactly this.
Moreover you know what is does: it plugs in q into p! (it applys p to q)
Your example of course is:
square: int -> int (so 'a and 'b here need both to be int as you use square in place of q)
3 which has type int so the expression F square 3 is wellformed
It evaluates as:
F square 3
{ def F }
= square 3
{ def square }
= 3*3
{ arithmetic }
= 9
Related
Usually test which contain question about SML have questions that ask you to find the signature/type of a function.
For example - What is the type of the following function:
fun foo f g x y = f (f x (g x) y) y;
Solution:
val foo = fn : ('a -> 'b -> 'b -> 'a) -> ('a -> 'b) -> 'a -> 'b -> 'b -> 'a
I was wondering if there is a good algorithm I could follow in order to solve those kind of questions. Every time I try to solve one of those, I get confused and fail.
Start with what you know, then figure out a bit here and a bit there until there are no unknowns.
Here is one possibility:
Call the unknown types FOO, F, G, X, and Y, respectively.
Then look for something small and easy and start assigning types.
(g x)
is clearly an application of a function to one argument.
Set X = a and G = a -> b.
Then look at the enclosing expression:
(f x (g x) y)
| |
v v
a b
So far, we know that F = a -> b -> Y -> C, for some C.
Go outwards again:
f (f x (g x) y) y
Since both x and (f x (g x) y) are first arguments to f, they must be the same type a, and the same idea applies to y and (g x), giving them the type b.
So, F = a -> b -> b -> a and, since the outer f is only given two arguments, the type of the right-hand side must be b -> a.
Thus
X = a
Y = b
G = a -> b
F = a -> b -> b -> a
FOO = (a -> b -> b -> a) -> (a -> b) -> a -> b -> (b -> a)
And, since arrows associate to the right, FOO is equivalent to
(a -> b -> b -> a) -> (a -> b) -> a -> b -> b -> a
There are several ways to derive the type of a function depending on how close to the compiler's algorithm you want to go and how much you want to cut corners with intuition, which can come handy in practice and perhaps in exams, depending on the focus of the exam.
An example by Ionuț G. Stan cuts very few corners, and has a quite verbose notation. This mechanical approach is very safe, spells out everything and takes some time.
This current example by molbdnilo takes a middle ground and does some equational reasoning, but also relies on some level of intuition. I think this is generally the way you want to be able to do it, since it takes less time and space by hand.
An example by me links to various other examples for a diversity in practical approaches.
Whilst revising for my programming languages exam, there are a few type inference questions for the Standard ML section, I can do most of them by doing type inference in my head, and I'm quite good at it, however there is one question that leaves me stumped.
I have to write a function of type:
('a -> ('b -> 'c)) -> ('a -> 'b) -> ('a -> 'c)
So in my head I should have a function with two arguments that are functions, f and g. Both would take an argument, x, but I cannot add that argument x into this function as it only takes two arguments, so I am left to create this function using the o operator, for pipe-lining functions.
So f takes an argument, and returns a function
g takes an argument, and returns a value.
Then the overall function takes a value and returns a value.
I'm not sure how I can apply f and g using only the o operator to imply those rules.
Any help would be extremely appreciated :)
Thanks, Ciaran
As you already mentioned, you need to write a function of two arguments:
fun my_function f g = body
where f : 'a -> 'b -> 'c and g : 'a -> 'b and body : 'a -> 'c.
Since body has type 'a -> 'c, we can write it as
body = fn x => body'
where body' has type 'c and x : 'a.
Observe, that f x : 'b -> 'c and g x : 'b, and if you have a function of type 'b -> 'c and a value of type 'b it's easy to construct a value of type 'c by applying the function to the argument: (f x) (g x).
The above gives us:
fun my_function f g = fn x => (f x) (g x)
or, alternatively, moving x to the left-hand side of the definition we get:
fun my_function f g x = f x (g x)
By the way, if you are familiar with combinatory logic, then you could notice that the resulting function represents the S combinator.
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 :)
Consider a recursive function, say the Euclid algorithm defined by:
let rec gcd a b =
let (q, r) = (a / b, a mod b) in
if r = 0 then b else gcd b r
(This is a simplified, very brittle definition.) How to memoize such a function? The classical approach of defining a high-order function memoize : ('a -> 'b) -> ('a -> 'b)
adding memoization to the function is here useless, because it will only save time on the first call.
I have found details on how to memoize such function in Lisp or Haskell:
How do I memoize a recursive function in Lisp?
Memoization with recursion
These suggestions rely on the ability found in Lisp to overwrite the symbol definition of a function or on the “call-by-need” strategy used by Haskell, and are therefore useless in OCaml.
The winning strategy is to define the recursive function to be memoized in a continuation passing style:
let gcd_cont k (a,b) =
let (q, r) = (a / b, a mod b) in
if r = 0 then b else k (b,r)
Instead of defining recursively the gcd_cont function, we add an argument, the “continuation” to be called in lieu of recursing. Now we define two higher-order functions, call and memo which operate on functions having a continuation argument. The first function, call is defined as:
let call f =
let rec g x =
f g x
in
g
It builds a function g which does nothing special but calls f. The second function memo builds a function g implementing memoization:
let memo f =
let table = ref [] in
let compute k x =
let y = f k x in
table := (x,y) :: !table; y
in
let rec g x =
try List.assoc x !table
with Not_found -> compute g x
in
g
These functions have the following signatures.
val call : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b = <fun>
val memo : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b = <fun>
Now we define two versions of the gcd function, the first one without memoization and the second one with memoization:
let gcd_call a b =
call gcd_cont (a,b)
let gcd_memo a b =
memo gcd_cont (a,b)
# let memoize f =
let table = Hashtbl.Poly.create () in
(fun x ->
match Hashtbl.find table x with
| Some y -> y
| None ->
let y = f x in
Hashtbl.add_exn table ~key:x ~data:y;
y
);;
val memoize : ('a -> 'b) -> 'a -> 'b = <fun>
# let memo_rec f_norec x =
let fref = ref (fun _ -> assert false) in
let f = memoize (fun x -> f_norec !fref x) in
fref := f;
f x
;;
val memo_rec : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b = <fun>
You should read the section here: https://realworldocaml.org/v1/en/html/imperative-programming-1.html#memoization-and-dynamic-programming in the book Real World OCaml.
It will help you truly understand how memo is working.
I am new to Ocaml and want help with recursive function defined on a recursive data type. I have defined a data type as follows
type 'a slist = S of 'a sexp list
and
'a sexp = Symbol of 'a | L of 'a slist
The function(subst) I'm writing checks for a symbol a in the defined slist and substitutes it by b. For ex subst 1 10 S[ 1; 4; S[L[3; 1;]; 3];] returns S[10; 4; S[L[S[3; 10;]]; 3;]
. My code is as follows
let rec subst a b sl = match sl with
S s -> match s with
[] -> []
| p :: q -> match p with
Symbol sym -> if sym = a then S[b] :: (**subst** a b S[q]) else
S[p] :: (subst a b S[q])
L l -> (subst a b l) :: (subst a b S[q])
| L lis -> subst a b lis;;
I am getting the error :
This function is applied to too many arguments; Maybe you forgot a ';'
Please help
Your type can be defined in a simpler way, you don't need slist:
type 'a sexp = Symbol of 'a | L of 'a sexp list
Your problem is that subst a b S[q] is read as subst a b S [q], that is the function subst applied to 4 arguments. You must write subst a b (S[q]) instead.