I'm practicing with SML and I'm doing a small assignment where we have to implement Church numerals defined as:
datatype 'a church = C of ('a -> 'a) * 'a -> 'a
example val
ZERO = C(fn (f,x) => x)
I have already implemented the functions:
create: int -> 'a church
churchToInt: 'a church -> int
and SUC which returns the successor of a Church numeral.
Now I have to implement the function
PRED: 'a church -> 'a church * 'a church
which returns the tuple of (predecessor, current numeral). I am not allowed to use churchToInt, I should directly work with Church numerals. Apparently this is solvable in one line by passing a specific argument.
I was thinking of just using SUC over and over until we hit the right number but there is no way for me to compare the 2 Church numerals. I am completely stuck on this.
suppose you want to construct the function that give you the pred of N.
You have to use pairs on numbers
like this (0,1) (1,2) ....(n,n+1)
and construct the succPair function
to go from (n-1,n) to (n,n+1)
and then you apply succPair N times on (0,1)
and last step you just apply snd on the last result I described
and then boom! you get your pred of N
look here to get the picture http://m2-info-upmc.blogspot.fr/2012/11/predecesseur-sur-les-entiers-de-church.html
You must have forced it to by an int in your subPred.
Related
I'm trying to built a function that zips the 2 given function, ignoring the longer list's length.
fun zipTail L1 L2 =
let
fun helper buf L1 L2 = buf
| helper buf [x::rest1] [y::rest2] = helper ((x,y)::buf) rest1 rest2
in
reverse (helper [] L1 L2)
end
When I did this I got the error message:
Error: right-hand-side of clause doesn't agree with function result type [circularity]
I'm curious as of what a circularity error is and how should I fix this.
There are a number of problems here
1) In helper buf L1 L2 = buf, the pattern buf L1 L2 would match all possible inputs, rendering your next clause (once debugged) redundant. In context, I think that you meant helper buf [] [] = buf, but then you would run into problems of non-exhaustive matching in the case of lists of unequal sizes. The simplest fix would be to move the second clause (the one with x::rest1) into the top line and then have a second pattern to catch the cases in which at least one of the lists are empty.
2) [xs::rest] is a pattern which matches a list of 1 item where the item is a nonempty list. That isn't your attention. You need to use (,) rather than [,].
3) reverse should be rev.
Making these changes, your definition becomes:
fun zipTail L1 L2 =
let
fun helper buf (x::rest1) (y::rest2) = helper ((x,y)::buf) rest1 rest2
| helper buf rest1 rest2 = buf
in
rev (helper [] L1 L2)
end;
Which works as intended.
The error message itself is a bit hard to understand, but you can think of it like this. In
helper buf [x::rest1] [y::rest2] = helper ((x,y)::buf) rest1 rest2
the things in the brackets on the left hand side are lists of lists. So their type would be 'a list list where 'a is the type of x. In x::rest1 the type of rest1 would have to be 'a list Since rest1 also appears on the other side of the equals sign in the same position as [x::rest1] then the type of rest1 would have to be the same as the type of [x::rest1], which is 'a list list. Thus rest1 must be both 'a list and 'a list list, which is impossible.
The circularity comes from if you attempt to make sense of 'a list list = 'a list, you would need a type 'a with 'a = 'a list. This would be a type whose values consists of a list of values of the same type, and the values of the items in that list would have to themselves be lists of elements of the same type ... It is a viscous circle which never ends.
The problem with circularity shows up many other places.
You want (x::rest1) and not [x::rest1].
The problem is a syntactic misconception.
The pattern [foo] will match against a list with exactly one element in it, foo.
The pattern x::rest1 will match against a list with at least one element in it, x, and its (possibly empty) tail, rest1. This is the pattern you want. But the pattern contains an infix operator, so you need to add a parenthesis around it.
The combined pattern [x::rest1] will match against a list with exactly one element that is itself a list with at least one element. This pattern is valid, although overly specific, and does not provoke a type error in itself.
The reason you get a circularity error is that the compiler can't infer what the type of rest1 is. As it occurs on the right-hand side of the :: pattern constructor, it must be 'a list, and as it occurs all by itself, it must be 'a. Trying to unify 'a = 'a list is like finding solutions to the equation x = x + 1.
You might say "well, as long as 'a = 'a list list list list list ... infinitely, like ∞ = ∞ + 1, that's a solution." But the Damas-Hindley-Milner type system doesn't treat this infinite construction as a well-defined type. And creating the singleton list [[[...x...]]] would require an infinite amount of brackets, so it isn't entirely practical anyways.
Some simpler examples of circularity:
fun derp [x] = derp x: This is a simplification of your case where the pattern in the first argument of derp indicates a list, and the x indicates that the type of element in this list must be the same as the type of the list itself.
fun wat x = wat [x]: This is a very similar case where wat takes an argument of type 'a and calls itself with an argument of type 'a list. Naturally, 'a could be an 'a list, but then so must 'a list be an 'a list list, etc.
As I said, you're getting circularity because of a syntactic misconception wrt. list patterns. But circularity is not restricted to lists. They're a product of composed types and self-reference. Here's an example without lists taken from Function which applies its argument to itself?:
fun erg x = x x: Here, x can be thought of as having type 'a to begin with, but seeing it applied as a function to itself, it must also have type 'a -> 'b. But if 'a = 'a -> 'b, then 'a -> b = ('a -> 'b) -> 'b, and ('a -> 'b) -> b = (('a -> 'b) -> b) -> b, and so on. SML compilers are quick to determine that there are no solutions here.
This is not to say that functions with circular types are always useless. As newacct points out, turning purely anonymous functions into recursive ones actually requires this, like in the Y-combinator.
The built-in ListPair.zip
is usually tail-recursive, by the way.
I'm trying to understand better the OCaml type inference. I created this example:
let rec f t = match t with
| (l,r) -> (f l)+(f r)
| _ -> 1
and I want to apply it on any binary tuple (pair) with nested pairs, to obtain the total number of leafs. Example: f ((1,2),3)
The function f refuses to compile, because a contradiction in types at (f l): "This expression has type 'a but an expression was expected of type 'a * 'b".
Question: 'a being any type, could not also be a pair, or else be handled by the _ case? Is any method to walk tuples of arbitrary depth without converting them to other data structures, such as variants?
PS: In C++ I would solve this kind of problem by creating two template functions "f", one to handle tuples and one other types.
There is a way to do this, although I wouldn't recommend it to a new user due to the resulting complexities. You should get used to writing regular OCaml first.
That said, you can walk arbitrary types in a generic way by capturing the necessary structure as a GADT. For this simple problem it is quite easy:
type 'a ty =
| Pair : 'a ty * 'b ty -> ('a * 'b) ty
| Other : 'a ty
let rec count_leaves : type a . a -> a ty -> int =
fun a ty ->
match ty with
| Pair (ta, tb) -> count_leaves (fst a) ta + count_leaves (snd a) tb
| Other -> 1
Notice how the pattern matching on the a ty here corresponds to the pattern matching on values in your (poorly typed) example function.
More useful functions could be written with a more complete type representation, although the machinery becomes heavy and complicated once arbitrary tuples, records, sum types, etc have to be supported.
Any combination of tuples will have a value shape completely described by it's type (because there is no "choice" in the type structure) - hence the "number of leaves" question can be answered completely statically at compile-time. Once you have a function operating on such type - this function is fixed to operate on that specific type (and shape) only.
If you want to build a tree that can have different shapes (but same type - hence can be handled by same function) - you need to add variants to the mix, i.e. classic type 'a tree = Leaf of 'a | Node of 'a tree * 'a tree, or any other type that describes value with some dynamic "choice" of shape.
From an old exam I had this SML function and I should give an answer on what this function calculates.
fun guess(e,(a,b)) = if e then (a,b) else (b,a)
The signature is bool * ('a * 'a) -> 'a * 'a but I have no clue what the purpose of this function is - despite the fact that it returns either (a,b) or (b,a).
Can anyone light me up?
If the condition is true it leaves (a,b) alone, otherwise it reverses it. There really isn't anything more to say about what it computes. As to borderline plausible motivation, sometimes ordered pairs need to be sorted in various ways. For example, guess(a<=b,(a,b)) will reverse (a,b) if a > b.
Write an Ocaml function list_print : string list -> unit that prints all the strings in a list from left to right:
So Lets say I've got an Ocaml function list_print: string list -> unit that prints all the strings in a list from left to write. Now the correct solution is:
let list_print lst = List.fold_left (fun ( ) -> fun s -> print_string s) () lst;;
But When writing my solution, I wrote it as such:
let list_print lst = List.fold_left (fun s -> print_string s) () lst;;
But this gave me
Error: This expression has type unit but an expression was expected of type 'a -> string
Why is it that I need that first parameter fun() -> before the fun s? I'm still new to Ocaml so this type system is quite confusing to me
The purpose of fold_left (and fold_right) is to accumulate a value as you go along. The extra parameter is this accumulated value.
You can use List.iter for your problem. It doesn't accumulate a value.
You could think of List.iter as a version of List.fold_left that accumulates values of type unit. And, in fact, you could implement it that way:
let iter f = List.fold_left (fun () a -> f a) ()
The point (as always with unit) is that there's only one value of the type, so it represents cases where the value isn't interesting.
You want to use List.fold_left, that's fine, but you should start by reading the documentation for that function. The official documentation is quite short:
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
List.fold_left f a [b1; ...; bn] is f (... (f (f a b1) b2) ...) bn.
The first thing is the type of that function. The type is
('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
In other words, the function fold_left has three arguments and one result value. The first argument has type ('a -> 'b -> 'a). The second argument has type 'a. The third argument has type 'b list. The result value of the function has type 'a.
Now, in your case, you want to print the strings. So you do not actually need any result value, you need a side effect. However, in OCaml all functions must have a result value. So you use the empty value, (), which has type unit. Therefore, the type parameter 'a will be equal to unit in your case.
The type parameter 'b is string because you are required to work on the list of strings.
Therefore, in your case the function fold_left must have the type
(unit -> string -> unit) -> unit -> string list -> unit.
The first argument of fold_left must have the type unit->string->unit. In other words, it must be a function with two arguments, first argument is the empty value, i.e. (), the second argument a string. So the first argument to fold_left must be a function of this kind,
fun x y -> ...
where x must be of type unit and y of type string. Since x is going to be always equal to (), it is not necessary to write this argument as a variable x, instead we can simply write () or even the dummy argument _. (The syntax fun x -> fun y -> ... gives the same function as fun x y -> ....)
Now you can begin to figure out how fold_left works. Since this is obviously a homework question, I will leave this task to you.
I have a function sqrt which takes 2 floating point values, tolerance and number and gives out square root of the number within the specified tolerance. I use approximation method to do it.
let rec sqrt_rec approx tol number =
..................;;
let sqrt tol x = sqrt_rec (x/.2.0) tol x;;
I've another function map which takes a function and a list and applies the function to all elements of the list.
let rec map f l =
match l with
[] -> []
| h::t -> f h::map f t;;
Now I'm trying to create another function all_sqrt which basically takes 1 floating point value, 1 floating point list and maps function sqrt to all the elements.
let all_sqrt tol_value ip_list = List.map sqrt tol_value ip_list;;
It is obviously giving me error. I tried making tol_value also a list but it still throws up error.
Error: This function is applied to too many arguments;
maybe you forgot a `;'
I believe i'm doing mapping wrong.
The List module contains
val map2 : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list
which is used like this:
let all_sqrt tol_value ip_list = List.map2 sqrt tol_value ip_list
This sounds like homework, since you say you are limited to certain functions in your solution. So I'll try to give just some suggestions, not an answer.
You want to use the same tolerance for all the values in your list. Imagine if there was a way to combine the tolerance with your sqrt function to produce a new function that takes just one parameter. You have something of the type float -> float -> float, and you somehow want to supply just the first float. This would give you back a function of type float -> float.
(As Wes pointed out, this works because your sqrt function is defined in Curried form.)
All I can say is that FP languages like OCaml (and Haskell) are exceptionally good at doing exactly this. In fact, it's kind of hard not to do it as long as you mind the precedences of various things. (I.e., think about the parentheses.)
I don't know O'Caml, but I do know Haskell, and it looks to me like you are applying map to 3 arguments "sqrt tol_value ip_list" map only takes two arguments, and is of the type ('a -> 'b) -> 'a list -> 'b list which means it accepts a function (functions only take one input and return one output), and a list, and returns a new list.
http://en.wikipedia.org/wiki/Currying