I am new to logic programming and Prolog. The following Prolog program defines a predicate mul/3 for multiplying the first argument to the second argument, which results in the third argument, based on the equation x * y = z which is equivalent to (x − 1) * y + y = z:
mul(0, _, 0).
mul(X, Y, Z) :-
ground(X),
succ(U, X),
add(V, Y, Z),
mul(U, Y, V).
mul(X, Y, Z) :-
var(X),
add(V, Y, Z),
mul(U, Y, V),
succ(U, X).
add(0, Y, Y).
add(X, Y, Z) :-
ground(X),
ground(Z),
succ(U, X),
succ(V, Z),
add(U, Y, V).
add(X, Y, Z) :-
ground(X),
var(Z),
succ(U, X),
add(U, Y, V),
succ(V, Z).
add(X, Y, Z) :-
ground(Z),
var(X),
succ(V, Z),
add(U, Y, V),
succ(U, X).
But it exhausts resources with queries in this argument mode:
?- mul(X, Y, 2).
X = 1, Y = 2
; X = 2, Y = 1
;
Stack limit (0.2Gb) exceeded
Stack sizes: local: 0.2Gb, global: 20.8Mb, trail: 10.4Mb
Stack depth: 452,739, last-call: 0%, Choice points: 452,716
In:
[452,739] add(_1326, 0, 0)
[452,738] add(_1354, 0, 1)
[452,737] add(_1382, 0, 2)
[452,736] mul(_1410, 0, 2)
[452,735] mul(_1438, 0, 2)
How to fix this recursive multiplication?
The program works okay in the sense that it gives the two solutions, X = 1, Y = 2 and X = 2, Y = 1. It then goes into an infinite search for other solutions.
The problem is with this rule:
mul(X, Y, Z) :-
var(X),
add(V, Y, Z),
mul(U, Y, V),
succ(U, X).
Here mul(U, Y, V) recurses in a way that the first argument is not ground, but the previous rules assume that it is (when V is not zero). Simply swapping the first two arguments solves the problem.
It is still not perfect though, consider
?- mul(2, 3, X).
false.
Here the problem is in the previous rule:
mul(X, Y, Z) :-
ground(X),
succ(U, X),
add(V, Y, Z),
mul(U, Y, V).
The call to add(V, Y, Z) becomes add(V, 3, Z), which is under-defined. Swapping it with the next mul solves this:
mul(X, Y, Z) :-
ground(X),
succ(U, X),
mul(U, Y, V),
add(V, Y, Z).
So is it okay now? Not really, e.g.
?- mul(X, 3, 6).
false.
Try to go through it with
?- trace, mul(X,3,6).
and find where the problem lies.
--- EDIT ---
Okay, so let's try this from scratch.
To simplify things, first look at the case when the first two arguments are not variables:
% add1(+X, +Y, ?Z) [semidet]
add1(0, Y, Y) :-
!.
add1(X, Y, Z) :-
succ(X1, X),
add1(X1, Y, Z1),
succ(Z1, Z).
% mul1(+X, +Y, ?Z) [semidet]
mul1(0, _, 0) :-
!.
mul1(X, Y, Z) :-
succ(X1, X),
mul1(X1, Y, Z1),
add1(Z1, Y, Z).
Then the other case, when the sum/product is known:
% add2(?X, ?Y, +Z) [nondet]
add2(0, Y, Y).
add2(X, Y, Z) :-
succ(Z1, Z),
add2(X1, Y, Z1),
succ(X1, X).
% mul2(?X, ?Y, +Z) [nondet]
mul2(X, Y, 0) :-
!,
(X = 0; Y = 0).
mul2(X, Y, Z) :-
nonvar(Y),
!,
succ(Y1, Y),
add2(Z1, X, Z),
mul2(X, Y1, Z1).
mul2(X, Y, Z) :-
add2(Z1, Y, Z),
mul2(X1, Y, Z1),
succ(X1, X).
Note that when the third rule in mul2 recurses, its second argument will be known, and that is used by the second rule. This is very similar to what you have written originally.
Finally, you can create a rule to choose the one you need:
add(X, Y, Z) :-
nonvar(Z) -> add2(X, Y, Z); add1(X, Y, Z).
mul(X, Y, Z) :-
nonvar(Z) -> mul2(X, Y, Z); mul1(X, Y, Z).
(Of course, you can unite these rules using var(X) etc., but I think it is much clearer this way.)
I am trying to define a function wrapper that curries a tuple in SML.
fun curry f = fn (x, y) z => f x y z;
Gives me the error
Non-identifier applied to a pattern.
I am new to ML and not sure why the pattern matching in fn doesn't work.
How could I make this work?
I am trying to define a function wrapper that curries a tuple in SML.
fun curry f = fn (x, y) z => f x y z;
How could I make this work?
Closures in SML don't allow for multiple arguments, but you can nest them instead.
What curry usually does is take a function f that normally accepts a tuple (x, y) and instead returns a modified function that takes x and y separately. Here is a number of equivalent ways to define curry:
fun curry f x y = f (x, y)
fun curry f x = fn y => f (x, y)
fun curry f = fn x => fn y => f (x, y)
val curry = fn f => fn x => fn y => f (x, y)
Its opposite, uncurry instead takes a function f that takes x and y separately and returns a modified function that takes (x, y). Here is one way to write uncurry:
fun uncurry f (x, y) = f x y
It's easy to mix up the two.
One way to fix the function you've written so that it compiles is insert an extra => fn:
fun what_is_this f = fn (x, y) => fn z => f x y z
(* ^- there *)
Before giving it a name, let's analyse what it does. It has the type signature:
fn : ('a -> 'b -> 'c -> 'd) -> 'a * 'b -> 'c -> 'd
(* now a tuple -^ ^- still curried *)
meaning that it takes a function of three curried arguments (x, y and z) and returns a modified function where the first two arguments are now in a tuple (uncurried) and the third is still curried. This is really a less generic version of uncurry. A more clear way of writing it would be:
fun what_is_this f (x, y) z = f x y z
If you use uncurry on a function of three arguments, you get the same effect, but you can't use what_is_this on anything with two curried arguments. So I'd say that this is a less useful variant of uncurry.
There are however other more useful variants of curry/uncurry. For example, you could make an uncurry_twice that converts f x y z into (uncurry_twice f) ((x, y), z), or an uncurry3 that converts f x y z into (uncurry3 f) (x, y, z):
fun uncurry_twice f = uncurry (uncurry f)
fun uncurry3 f (x, y, z) = f x y z
I created a function and helper function that find the number of repeating elements in a list, and what those elements.
let rec _encode l x =
match l with
| [] -> 0
| head::rest -> (if head = x then 1 else 0) + encode rest x
let encode l x = ((_encode l x), x)
In this case, I have to specify what that element is for it to search.
So this is a two part question. 1) How do I do it to return a list of tuples, with format (int * 'a) list, where int is the # of rep, and 'a is the element that is repeating.
2) How would I implement this using fold_right?
I was thinking something along the lines of:
let encode (l : 'a list) : (int * 'a) list = fold_right (fun (x,hd) lst ->
match x with
| [] -> 0
| hd :: rest -> if hd x then (x+1, hd) else (x, hd)) l []
Your attempt looks very confused:
It doesn't use lst, hd (the first one), or rest.
x is used as a list (match x with []) and a number (x+1).
The elements of x (list) are functions that return bools?? (... hd::rest -> ... if hd x)
The function sometimes returns a number (0) and sometimes a tuple ((x, hd)).
Here's how I'd do it:
let encode l =
let f x = function
| (n, y) :: zs when x = y -> (n + 1, y) :: zs
| zs -> (1, x) :: zs
in
fold_right f l []
Which is the same as:
let encode l =
let f x z = match z with
| (n, y) :: zs when x = y -> (n + 1, y) :: zs
| zs -> (1, x) :: zs
in
fold_right f l []
Which is the same as:
let encode l =
fold_right (fun x z ->
match z with
| (n, y) :: zs when x = y -> (n + 1, y) :: zs
| zs -> (1, x) :: zs
) l []
I have a university course about functional programming, where I use SML. As a preparation for the exam, I am working on some of the older exam sets without solutions.
One of the only questions I really have problems with is the following question using foldl:
Consider the program skeleton: fun
addGt k xs = List.foldl (...) ... xs;
Fill in the two missing pieces
(represented by the dots ...), so that
addGt k xs is the sum of those
elements in xs, which are greater than
k. For example, addGt 4 [1, 5, 2, 7,
4, 8] = 5 + 7 + 8 = 20
I am sure this is really easy, but I have a very hard time understanding the foldl and foldr functions.
What I have now is the following (which seems to be very wrong if you ask my compiler!):
fun addGt(k,xs) = List.foldl ( fn x => if x > k then op+ else 0) 0 xs;
I would really appreciate some help with this question, and maybe a very short comment which would cast some light on the foldl and foldr functions!
A solution that I just though of is the following:
fun addGt(k, xs) = List.foldl (fn (x, y) => if x >= 5 then x + y else y) 0 xs;
But let me explain. First of all check the type of the List.foldl function, it's:
('a * 'b -> 'b) -> 'b -> 'a list -> 'b
So List.foldl is a curried function that takes as first parameter another function of type ('a * 'b -> 'b). You used (fn x => if x > k then op+ else 0) which has type int -> int. You should instead provide List.foldl with a function that takes a tuple of type int * int and returns an int, so something like this: (fn (x, y) => do stuff). That's why your code didn't compile, you passed a wrong type of function in foldl.
Now you can think of foldl this way:
foldl f b [x_1, x_2, ..., x_(n - 1), x_n] = f(x_n, f(x_(n - 1), ..., f(x2, f(x1, b)) ...)) where f is a function of type ('a * 'b -> 'b), b is something of type 'b and the list [x_1, x_2, ..., x_(n - 1), x_n] is of type 'a list.
And similar for foldr you can think it in this way:
foldr f b [x_1, x_2, ..., x_(n - 1), x_n] = f(x_1, f(x_2, ..., f(x_(n - 1), f(x_ n, b))
If you call foldl f s ls on a list, ls = [x1, x2, ..., xn], then you get the result:
f(xn, ... f(x2, f(x1, s)))
That is, it starts by finding
a1 = f(x1, s)
Then
a2 = f(x2, a1)
and so on, until it's through the list.
When it's done, it returns an.
You can think of the a-values as being a sort of accumulator, that is, ai is the result as it would be if the list was only [x1, x2, ..., xi] (or rather, the first i elements of the list).
Your function will usually have the form:
fn (x, a) => ...
What you then need to do is think: Okay, if I have the next element in the list, x(i+1), and the value ai, which is the result for the list [x1, x2, ..., xi], what do I need to do to find the value a(i+1), which is the result for the list [x1, x2, ..., xi, x(i+1)].
s can be thought of as the value given to the empty list.
foldr works the same way, only you start from the back of the list instead of from the front.