From Learn You a Haskell:
Think about this list: [5]. That’s just syntactic sugar for 5:[]. On
the left side of the :, there’s a value; on the right side, there’s a
list. In this case, it’s an empty list. Now how about the list [4,5]?
Well, that desugars to 4:(5:[]). Looking at the first :, we see that
it also has an element on its left side and a list, (5:[]), on its
right side.
The same goes for a list like 3:(4:(5:6:[])), which could be written
either like that or like 3:4:5:6:[] (because : is right-associative)
or [3,4,5,6].
For the bolded part, I was expecting the growing list to culminate in 3:(4:(5:(6:[]))). This has something to do with my lack of understanding of currying, associativity, or both. Can someone tell me the flaw in my thinking?
Multiplication is associative. This means that (x * y) * z is the same as x * (y * z). However, : is not associative.
However, the terms "left-associative" and "right-associative" are different, and unrelated to the term "associative".
If * is left-associative, then x * y * z is the same thing as (x * y) * z. The parentheses are redundant.
If * is right-associative, then x * y * z is the same thing as x * (y * z). The parentheses are redundant.
Currying has nothing to do with this.
Since : is right-associative, [3,4,5,6] can be written as:
3:(4:(5:(6:[])))
3:4:(5:(6:[]))
3:(4:5:(6:[]))
3:4:5:(6:[])
3:(4:(5:6:[]))
3:4:(5:6:[])
3:(4:5:6:[])
3:4:5:6:[]
It's just a typo. There should be a parenthesis in the example (but it is the same behaviour without one, because of the associativity).
You say "I was expecting the growing list to culminate in 3:(4:(5:(6:[])))".
Indeed you are right. If you want to eliminate all syntactic sugar from [3,4,5,6], you will get 3:(4:(5:(6:[])))
You are puzzled by the fact that as you state in the comment in your question "the book says 3:(4:(5:6:[]))".
Again, you are right to be. In the interest of keeping presentation uniform, it shouldn't; this was probably a typo.
As far as Haskell syntax and semantics go though, there is nothing wrong with writing 3:(4:(5:6:[])) instead of 3:(4:(5:(6:[]))). What this boils down to is the question of whether 5:6:[] is the same as 5:(6:[]) or not. By the definition of right-associativity it is. Because : is right associative x:y:z = x:(y:z).
Just to add a geeky note here: by taking advantage of :'s right-associativity (i.e. not using parentheses), one can write 3:(4:(5:(6:[]))) quite concisely: 3:4:5:6:[]. This is only a single character longer than its syntactically sugared [3,4,5,6].
See also: http://en.wikipedia.org/wiki/Operator_associativity for more info on associativity.
Related
I have written the following code:
fun remove_element(nil, elem) = raise Empty
| remove_element(hd::tl, elem) = if(hd=elem) then tl else hd::remove_element(tl, elem);
but that function (which removed element elem from list) works for int. I need to make it work for real numbers, but I can't do it. I have tried a lot of ways of rewriting the function and also I used :real but these bring me errors.
Any suggestions?
Thank you
The accepted answer should have allowed you to finish your assignment, so I will show two other approaches for variations of your problem without worrying about doing your homework for you. As Kevin Johnson said, it isn't possible to directly compare two reals. It is possible to do so indirectly since a=b if and only if a<=b and b<=a. Often this is a bug, especially if the list in question is of numbers produced by numerical computations. But -- there are some situations where it makes sense to compare reals for equality so you should certainly be able to do so as long as you are clear that this is what you want. This leads to the following modification of your code:
fun remove_real([],x:real) = []
| remove_real(y::ys,x) =
if (y <= x andalso y >= x) then
remove_real(ys,x)
else
y::remove_real(ys,x);
A few points:
1) I changed it to remove all occurrences of the element from the list rather than just the first occurrence. This involved changing the basis case to returning the empty list since [] with y removed is just [] rather than an error situation. Also, rather than simply returning the tail if the element is found I return the recursive call applied to the tail to remove any additional occurrences later on. You could easily modify the code to make it closer to your original code.
2) I needed to put the explicit type annotation x:real so that SML could infer that the list was of type real list rather than type int list.
3) I replaced nil by [] for aesthetic reasons
4) I replaced your pattern hd::tl by y::ys. For one thing, hd and tl are built-in functions -- I see no reason to bind those identifiers to anything else, even if it is just local to a function definition. For another thing, the less visual clutter in a pattern the better.
5) I made more use of white space. Partially a matter of taste, but I think that fairly complicated clauses (like your second line) should be split across multiple lines.
If you want to go the route of including an error tolerance for comparing reals, I think that it makes most sense to include the tolerance as an explicit parameter. I find |x-y| < e to be more natural than two inequalities. Unfortunately, the built-in abs only applies to ints. If x - y is real then the expression
if x - y < 0.0 then y - x else x - y
returns the absolute value of x - y (it flips the sign in the case that it is neagative). As an added bonus -- the comparison with 0.0 rather than 0 is all that SML needs to infer the type. This leads to:
fun remove_elem([],x,tol) = []
| remove_elem(y::ys,x,tol) =
if (if x - y < 0.0 then y - x else x - y) < tol then
remove_elem(ys,x,tol)
else
y::remove_elem(ys,x,tol);
Typical output:
- remove_real([2.0, 3.1, 3.14, 3.145, 3.14], 3.14);
val it = [2.0,3.1,3.145] : real list
- remove_elem([2.0, 3.1, 3.14, 3.145, 3.14], 3.14,0.01);
val it = [2.0,3.1] : real list
- remove_elem([2.0, 3.1, 3.14, 3.145, 3.14], 3.14,0.001);
val it = [2.0,3.1,3.145] : real list
The issue is here: hd=elem
In languages like ML and Javascript, you cannot directly compare two reals as reals are bound to rounding errors.
You have to use a lambda range and define an interval instead. elem - lambda < hd andalso elem + lambda > hd
fun in_list (x : int, y : int list) =
if null y
then false
else if x=hd y then true
else in_list(x,tl y)
This is what my code currently looks like, it simply returns true if x appears in the the y list, false if not. The issue is I want it to be able to input "a" and ["a", "b", "c"] as well, or even have x be a list, and y be a list of lists. I am VERY new to ML (just started learning about it last week), and have searched for answers and cannot come up with anything.
If you change the first line to
fun in_list (x : ''a, y : ''a list) =
then it will behave as you want. Here ''a is an equality type variable that can stand for any type that supports the = operator.
You could also just leave out the types altogether and the most general correct type will be inferred.
Types can always be omitted in function declarations, with is only one exception: where overloading of operators could cause ambiguity. An example is
fun square x = x*x
because the type of x could be either int or real. (It will default to int, maybe not what you want.)
The point is that there is only one function hd. But the operator * can refer to two quite different functions.
I have written a program to evaluate a post-fix expression in prolog recursively from an expression list. For example, given the following list:
[+,1,2]
It should return 3. They way I have constructed my predicate is to call itself recursively until it reaches the end of the list so that it reads values backwards. (the same as reading this list from left to right:[2,1,+]).
My problem is that when I try to return more than one value through the recursive calls all the values suddenly disappear.
Here's the code:
eval_list([Head|Tail],_,Result):-
Tail==[], % last element of list
Result=Head,
write(Head),
write(' was stored in Result!\n').
eval_list([Head|Tail],Store1,Result):-
eval_list(Tail,Store2, NewResult),
(\+integer(Store2))
->
% if no integer is bound to Store2, bind Store1 to Head
Store1=Head,
Result is NewResult,
write(Head),
write(' is stored value!\n')
; (integer(Store2)) ->
% if an integer is bound to store2, we perform operation specified by the Head with the stored number
X is Store2+NewResult,
Result is X,
write('performed operation!\n')
;
% if doesnt catch either of these states the program is broken
( print('something broke\n'),
print(Store1),
nl,
print(Store2),
nl,
print(Head),
nl,
print(Result),
nl
).
I get the following output:
?- eval_list([+,1,2],X,Result).
2 was stored in Result!
1 is stored value!
something broke
_G1162
_L147
+
_G1163
true.
I don't understand why my values disappear, or if there is a better way to evaluate the list.
Some advice on your programming technique. You should use head matching and unification instead of explicit unification in the body of your predicate definitions, and if-else constructs. You should also avoid not tail-recursive recursion, unless your algorithm is inherently recursive (in-order tree traversal, for example). This will make the code easier to write, read, and understand. Right now, I don't even feel like debugging your code, but it looks like your Store2 would never be bound to an integer, and is always going to be an unbound variable, no matter what input your program has.
Now to your program. It is not clear what you are trying to achieve. If you only want to evaluate list of the form [Arithmetic_operator, Operand1, Operand2], it would be much easier to write:
arith_eval(Expression_list, Result) :-
Arithmetic_expr =.. Expression_list, % look up what =.. stands for!
Result is Arithmetic_expr.
I don't see the need for this overly complicated approach you are using.
If you want to be able to evaluate arbitrarily complex expressions, written in post-fix, with fixed operator arity (so you can say 2, 3, +, but not 2, 4, 1, +, for a sum of 7):
Read one element from your input
Push the element to the top of the stack
Try to reduce the stack:
pop operator and operands, if on top of the stack
evaluate
push result back on the top of the stack
When input is empty, your stack is your result
You could explicitly define the effect of different operators (here, only + and -) like this:
eval_stack([+,A,B|Tail],[Result|Tail]) :-
number(A), number(B),
!,
Result is B + A.
eval_stack([-,A,B|Tail],[Result|Tail]) :-
number(A), number(B),
!,
Result is B - A.
eval_stack(Stack,Stack).
Note how either an operator matches the top of your stack, and is applied when there are operands below it, pushing the result back on the stack, or the stack is left unchanged.
And you can push from your input to your stack:
evaluate([Next|Rest], Stack, Result) :-
eval_stack([Next|Stack],NewStack),
evaluate(Rest,NewStack,Result).
evaluate([],Result,Result). % end of input
So now you could call this with:
?- evaluate([2,3,+,3,6,-,+],[],Result).
Result = [2].
?- evaluate([2,3,4,-,-,5,+],[],Result).
Result = [8].
?- evaluate([2,3,4,-,-,5,+,1,3,2,-],[],Result).
Result = [1,1,8].
So these two predicates, evaluate(Input,Stack,Result), and eval_stack(Stack,NewStack) is all you would need for evaluating a valid post-fix arithmetic expressions with fixed-arity operators only.
I'm trying to figure out how to implement fixed point iteration in Ocaml. That is, given a function f and an x, I want to calculate what the final value of what f(f(f(x)...)) will be.
So for example, if my function is x/2 and my x=50, my answer should be 0.
So far, I have
let rec computed_fixed_point eq f x =
if (x == f x) then
x
else
computed_fixed_point eq f (f x)
This works for the function x/2 and x=50 (giving me 0), but for functions that go off to infinity or something other than 0, it doesn't seem to work.
Can another give me some advice? Thanks!
It's a little hard to understand the rationale of this problem. Not every function is going to have a fixed point. For example fun x -> (x + 1) mod 5. Not every function with a fixed point will reach the fixed point by repeated application from a distinct starting point. (I just did some googling, and fixed points like this are called "attractive fixed points".)
Here are some comments:
You shouldn't use ==, which is the physical equality operator. You possibly want to use =, equality of values.
However, I don't see what the eq parameter is for. Perhaps the caller is allowed to specify what equality to use. If so, you should use this instead of ==.
This is another prolog task that I can't solve at this moment. I have to write a predicat p(X,Y), where X is list of lists of number and Y is a list of numbers. The predicat has to verify:
1) if X can be presented as a concatenation between 2 elements from Y.
2) X has a odd number of elements.
3) Sum of all elements in X is last element in Y.
Maybe as a separate tasks 2, 3 could be written easy. Problem is at 1)
Thank you in advance. I feel sorry for posting such an easy tasks, but prolog really drives me crazy. I have read all my lections over and over again. But the situation is similar to this:
school: 3+x=5, x = ?
exam: cos(x+y+z) + lim (5x+y)/t = .... If you know what I mean. Thank you once again!
Checking for concatenations is done with append/3, which is more commonly used to build them but like many Prolog predicates works "in the opposite direction" as well. More specifically, append(A,B,C) checks whether C is the concatenation of A and B. So,
member(A, Y),
member(B, Y),
append(A, B, X)
checks whether there is a element A in Y and a element B in Y such that their concatenation unifies with X.
(Note that this does not check whether A and B are distinct elements of Y.)