I have an assignment where I need to implement church numerals in SML using the datatype: datatype 'a church = C of ('a -'a) * 'a -> 'a
I have to write the function create :int -> 'a church and a function churchToint
So far I have the following code:
datatype 'a church = C of ('a -> 'a) * 'a -> 'a
val ZERO = C(fn (f,x) => x)
fun subCreate 0 (f,x) = x
| subCreate n (f,x) = f (subCreate (n-1) (f,x))
fun create n = C(fn (f,x) => subCreate n (f,x));
fun churchToInt cn = cn (fn x => x + 1) 0;
I know I am pretty close. Can you please assist me in implementing this correctly? Thanks
You are right, you are quite close. There are only two minor mistakes in your churchToInt function:
You're not unpacking the church numeral. I.e. you treat your argument cn like a function, but churchToInt should accept a C containing a function, not a function itself. So change it to fun churchToInt (C cn) =, to unpack the function via pattern matching.
You're applying two arguments to the function using curry style, but C has been defined to contain a function taking a tuple. So instead of cn (fn x => x+1) 0, write cn ((fn x => x+1), 0).
With these two changes your code works fine.
Related
for an example, if a function receives a function as a factor and iterates it twice
func x = f(f(x))
I have totally no idea of how the code should be written
You just pass the function as a value. E.g.:
let apply_twice f x = f (f x)
should do what you expect. We can try it out by testing on the command line:
utop # apply_twice ((+) 1) 100
- : int = 102
The (+) 1 term is the function that adds one to a number (you could also write it as (fun x -> 1 + x)). Also remember that a function in OCaml does not need to be evaluated with all its parameters. If you evaluate apply_twice only with the function you receive a new function that can be evaluated on a number:
utop # let add_two = apply_twice ((+) 1) ;;
val add_two : int -> int = <fun>
utop # add_two 1000;;
- : int = 1002
To provide a better understanding: In OCaml, functions are first-class
values. Just like int is a value, 'a -> 'a -> 'a is a value (I
suppose you are familiar with function signatures). So, how do you
implement a function that returns a function? Well, let's rephrase it:
As functions = values in OCaml, we could phrase your question in three
different forms:
[1] a function that returns a function
[2] a function that returns a value
[3] a value that returns a value
Note that those are all equivalent; I just changed terms.
[2] is probably the most intuitive one for you.
First, let's look at how OCaml evaluates functions (concrete example):
let sum x y = x + y
(val sum: int -> int -> int = <fun>)
f takes in two int's and returns an int (Intuitively speaking, a
functional value is a value, that can evaluate further if you provide
values). This is the reason you can do stuff like this:
let partial_sum = sum 2
(int -> int = <fun>)
let total_sum = partial_sum 3 (equivalent to: let total_sum y = 3 + y)
(int = 5)
partial_sum is a function, that takes in only one int and returns
another int. So we already provided one argument of the function,
now one is still missing, so it's still a functional value. If that is
still not clear, look into it more. (Hint: f x = x is equivalent to
f = fun x -> x) Let's come back to your question. The simplest
function, that returns a function is the function itself:
let f x = x
(val f:'a -> 'a = <fun>)
f
('a -> 'a = <fun>)
let f x = x Calling f without arguments returns f itself. Say you
wanted to concatenate two functions, so f o g, or f(g(x)):
let g x = (* do something *)
(val g: 'a -> 'b)
let f x = (* do something *)
(val f: 'a -> 'b)
let f_g f g x = f (g x)
(val f_g: ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>)
('a -> 'b): that's f, ('c -> 'a): that's g, c: that's x.
Exercise: Think about why the particular signatures have to be like that. Because let f_g f g x = f (g x) is equivalent to let f_g = fun f -> fun g -> fun x -> f (g x), and we do not provide
the argument x, we have created a function concatenation. Play around
with providing partial arguments, look at the signature, and there
will be nothing magical about functions returning functions; or:
functions returning values.
So, I am trying to create a high order SML function that takes in a number and returns all the functions and returns its factors. I have done questions where I would take a list of values and return the values that are divisible but I never did anything like take a number and make a list out of it. Following the question:
Define a function factorize = fn: int -> int list that takes an integer and returns all its factors in a list. For example, factorize 12 will return [1, 2, 3, 4, 6, 12].
The second one is a tricky one, I couldn't understand how its done so dropping it here. I would appreciate any help I get on this one.
Define a function cfoldl that behaves exactly same as the standard foldl except that the type of the function argument does not take a 2-tuple’ instead, the input function should use the currying notation as is ’a -> ’b -> ’b. Thus, the type of cfoldl should be fn : (’a -> b -> ’b) -> ’b -> ’a list -> ’b. For example, cfoldl (fn a => fn b => a-b) 1 [1,2,3,4]; will return 3.
I made this for the foldl:
fun cfoldl f b [] = b
| cfoldl f b (x::xs) = cfoldl f (f (x, b)) xs;
Thank you!
factorize = fn: int -> int list that takes an integer and returns all its factors in a list
Here's a recursive function that takes a number and generates a list of numbers from 1 up to that number:
fun upto n =
let fun go i = if i < n
then i :: go (i+1)
else []
in go 1
end
Could you make a function isFactor x y that is true when x is a factor of y?
If you had such a function, could you modify the above function to make use of it?
a function cfoldl that should use the currying notation as is ’a -> ’b -> ’b
fun cfoldl f b [] = b | cfoldl f b (x::xs) = cfoldl f (f (x, b)) xs;
This is exactly foldl.
fun foldl f e [] = e
| foldl f e (x::xr) = foldl f (f(x, e)) xr;
Here, f : ('a * 'b) -> 'b because f is being used as f(x, e), so naturally it will assume a tuple. You can change the inferred type of f by using it differently.
Can you think of a way where f : 'a -> 'b -> 'b?
As I am going through the website:
http://www.cs.princeton.edu/courses/archive/fall14/cos326/sec/03/precept03_sol.ml
I have got a question according to the Ocaml structure. To be more specific, I have questions according to the code:
let rec reduce (f:'a -> 'b -> 'b) (u:'b) (xs:'a list) : 'b =
match xs with
| [] -> u
| hd::tl -> f hd (reduce f u tl);;
What does the f hd do at the very last line? (I understand that reduce f u tl is calling the function itself again.)
My second question is how to use a function to implement another function in Ocaml. For the code:
let times_x (x: int) (lst: int list) : int list =
map (fun y -> y*x) lst
What does fun y -> y*x do? what does lst do at the end of the code?
Thank you for the help!
The code that has been provided is a reduce function that takes three parameters - a function that maps inputs of type 'a and 'b to an output of type 'b, a value of type 'b, and as list of elements of type 'a.
For example, the length example from the lecture:
let length (lst: int list) : int =
reduce (fun _ len -> len + 1) 0 lst
The first parameter to reduce is a function that, when given two parameters, discards the first one and returns the second parameter incremented by one. The second is a value (0) to be used as an accumulator. The third is a list to find the length of.
The behavior of this recursive reduce function is to return the second parameter (an accumulator as used in the length example) once the provided list is empty, and otherwise run the provided function using the head of the list and the recursed value.
Once again going to the length example, say we give it a list with a single element [1].
Our call to length becomes reduce (fun _ len -> len + 1) 0 [1]
Recall reduce:
let rec reduce (f:'a -> 'b -> 'b) (u:'b) (xs:'a list) : 'b =
match xs with
| [] -> u
| hd::tl -> f hd (reduce f u tl);;
First, we match [1] against [], which fails. Since it is a non-empty list, we run f hd (reduce f u tl)
Recall that f is the parameter that length provided: fun _ len -> len + 1
Therefore, we effectively run the following:
(fun _ len -> len + 1) 1 (reduce (fun _ len -> len + 1) 0 [])
In this case, the length function discards the first parameter since the values in the list are not necessary to know the length of the list.
The recursive portion will match against [] and return the value of u at the time, which is 0.
Therefore, one level up, (fun _ len -> len + 1) 1 (reduce (fun _ len -> len + 1) 0 []) becomes (fun _ len -> len + 1) 1 0 and returns 0 + 1, simplifying to our expected value 1, which represents the length of the list.
Now, to your second question, in regards to times_x. This performs a mapping. For example, we can map [1;2;3;4;5] to [3;6;9;12;15] with a mapping fun x -> x * 3.
Here times_x is defined as follows:
let times_x (x: int) (lst: int list) : int list =
map (fun y -> y*x) lst
times_x takes an integer and a list. Using the above example, we could call it with times_x 3 [1;2;3;4;5] to get [3;6;9;12;15].
Beyond this I recommend looking into how map and reduce functions work in general.
I hope this answer was adequate at addressing your question.
I'm using SML recently and I'm trying to solve a problem.
I should create a function that accept an int list and return even int list,
I've already created it :
fun evens [] = [] |
evens [x] = [x] |
evens(x::xs) =
case x mod 2 of
0 => x::evens xs |
1 => evens xs;
which gives the correct result but I need to use foldr
this is what I came up with:
fun evens [] = [] |
evens(x::xs) =
case x mod 2 of
0 => foldr (op ::) evens xs [x] |
1 => evens xs;
but it is not working, I'm still confused with how to use foldr in this case.
any advice?
First of all, with foldr you should be looking for a 1-line definition rather than a recursive definition using patterns and cases. The point of foldr is that it incorporates a common recursion pattern -- you just need to use the pattern.
The type of foldr is
fn : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
In your case 'b is int list and 'a is int. The 'b between the arrows in the middle of foldr's type is the seed value. It typically corresponds to a basis value. When you are constructing lists this basis value is typically []. Thus -- you need to concentrate on the key question of what should be folded over the list. In other words -- what function of type ('a * 'b -> 'b) should you pass to foldr? In your case you need to pass a function of type
int * int list -> int list
this should be a function which, when given an int and an int list either tacks the int onto the list (if it is even) or leaves the list alone. You could define this function ahead of time, define it using let, or just use an anonymous function.
Under the assumption that this is homework, I don't want to give a complete answer, but here is a function which uses foldr to obtain the positive entries in a list:
fun positives xs =
foldr (fn (x,xs) => if x >= 0 then x::xs else xs) [] xs;
-
- positives [3,~2,4,5,0,~1,~1,5];
val it = [3,4,5,0,5] : int list
I have this code to filter list of string that the first letter is capital:
fun f s = Char.isUpper(String.sub(s,0));
fun only_capitals (xs : string list) = List.filter(f , xs);
But when compile, I always receive error :
operator domain: 'Z -> bool
operand: (string -> bool) * string list
in expression:
List.filter (f,xs)
What does this error mean? How to fix it?
Type signature of List.filter is
val filter : ('a -> bool) -> 'a list -> 'a list
So you need to give List.filter two distinct arguments, not one argument which happens to be a tuple.
You need to change it to:
fun only_capitals (xs : string list) = List.filter f xs
filter takes 2 arguments, a function f ('a -> bool) and a list.
It's easy to confuse syntax of passing a tuple in ML with the sytax of functional application in other languages.
You could also define it as:
val only_capitals = List.filter f
Functions in ML can take only one argument. Description from here (see also notes and video there).
List.filter is so called curried function, so List.filter f xs is actually (List.filter f) xs where List.filter f is a function. We have to provide f (fn: a -> bool) as an argument to List.filter, not tuple (f, xs).
Here is a simple example. When we call is_sorted 1 we get a closure with x in its environment. When we call this closure with 2 we get true because 1 <= 2.
val is_sorted = fn x => (fn y => x <= y)
val test0 = (is_sorted 1) 2
val is_sorted = fn : int -> int -> bool
val test0 = true : bool
In the SML document, it states that:
filter f l
applies f to each element x of l, from left to right, and returns the list of those x for which f x evaluated to true, in the same order as they occurred in the argument list.
So it is a curried function.
In the SML document, the filter function in the List structure listed as
filter f l
where it takes curried arguments f and l
Instead of passing the arguments in a tuple, you have to provide a function and the list separated by spaces. The answer will be like this
fun only_capitals (xs: string list) =
List.filter (fn s => Char.isUpper(String.sub(s,0))) xs