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
Related
I am really new to Haskell and also really confused about how to implement for loops since I know we need to use recursion for them.
For example, I have a list [1,2,2,4,1] and want to write a function to change every 2 to a 3. How would I go about doing this? In Java, I know I would write the following
public void replace_two(List<Integer> ints) {
int i = 0;
for (int x: ints) {
if (x == 2) {
ints.set(i, 3);
}
i++;
}
System.out.println(ints);
}
but I am not sure how I could reproduce something else like this with Haskell?
There's not a single replacement for a for loop in Haskell. The replacement depends on exactly what you want to do. In this case, a map would be appropriate:
replace_two = map go
where
go 2 = 3
go x = x
And it works like this:
Prelude> replace_two [1,2,2,4,1]
[1,3,3,4,1]
Prelude>
Haskell uses a combination of different ways to 'sort of' loop over data, e.g. list.
The two important things helping this is:
Ease of declaring a function and passing it around similar to what we do to a variable in oops languages
Extensive pattern matching
So for example I declare a function in haskell to return 2 if input is 3 else return input.
return2 x = if x == 3 then 2 else x
Now we want to apply this function to every element of the list. So we will use pattern matching.
apply (x:xs) = return2 x : apply xs
apply [] = []
Here the pattern x:xs will break the list and take the first element in x while xs will have the remainder of the list. Inside the function you can see we have applied it recursively.
I have not checked the above code in IDE so it might have syntax errors, also there are other things you will want to validate (end of list, in above code the function would cause exception).
The above pattern is quite common, so there is another function in the core libraries that can do this, and is called map. So you could do:
map return2 [your list]
As I said, in haskell there are many ways to essentially loop over things, but at the base they break down to applying the function to individual items in the data structure. There are many haskell functions built on top of it like map, fold, etc.
I would suggest you use one of the several resources online to get more familiar with Haskell constructs. One that I liked and was easy to follow is Learn you a Haskell
Using map with an anonymous function:
λ> map (\x -> if x==2 then 3 else x) [1,2,2,4,1]
[1,3,3,4,1]
Another basic approach using patterns and recursion.
replace :: [Int] -> [Int]
replace [] = [] -- base case
replace (2:x) = 3:replace(x) --if 2 then replace by 3
replace (y:x) = y:replace(x) -- do nothing
Except map, maybe you can use forM from Control.Monad to mimic the for loop in other imperative languages:
import Control.Monad
arr = [1, 2, 2, 4, 1]
forM arr $ \i ->
if i == 2 then return 3 else return i
However, you need to understand what is Monad.
I want to convert a sequence to a list using List.init. I want at each step to retrieve the i th value of s.
let to_list s =
let n = length s in
List.init n
(fun _i ->
match s () with
| Nil -> assert false
| Cons (a, sr) -> a)
This is giving me a list initialized with the first element of s only. Is it possible in OCaml to initialize the list with all the values of s?
It may help to study the definition of List.init.
There are two variations depending on the size of the list: a tail recursive one, init_tailrec_aux, whose result is in reverse order, and a basic one, init_aux. They have identical results, so we need only look at init_aux:
let rec init_aux i n f =
if i >= n then []
else
let r = f i in
r :: init_aux (i+1) n f
This function recursively increments a counter i until it reaches a limit n. For each value of the counter that is strictly less than the limit, it adds the value given by f i to the head of the list being produced.
The question now is, what does your anonymous function do when called with different values of i?:
let f_anon =
(fun _i -> match s () with
|Nil -> assert false
|Cons(a, sr) -> a)
Regardless of _i, it always gives the head of the list produced by s (), and if s () always returns the same list, then f_anon 0 = f_anon 1 = f_anon 2 = f_anon 3 = hd (s ()).
Jeffrey Scofield's answer describes a technique for giving a different value at each _i, and I agree with his suggestion that List.init is not the best solution for this problem.
The essence of the problem is that you're not saving sr, which would let you retrieve the next element of the sequence.
However, the slightly larger problem is that List.init passes only an int as an argument to the initialization function. So even if you did keep track of sr, there's no way it can be passed to your initialization function.
You can do what you want using the impure parts of OCaml. E.g., you could save sr in a global reference variable at each step and retrieve it in the next call to the initialization function. However, this is really quite a cumbersome way to produce your list.
I would suggest not using List.init. You can write a straightforward recursive function to do what you want. (If you care about tail recursion, you can write a slightly less straightforward function.)
using a recursive function will increase the complexity so i think that initializing directly the list (or array) at the corresponding length will be better but i don't really know how to get a different value at each _i like Jeffrey Scofield said i am not really familiar with ocaml especially sequences so i have some difficulties doing that:(
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'm having some trouble understanding what variants is in SML and how you determine the variant for a recursive function. I got the explanation:
"A variant for a (recursive) function is any expression over the function's arguments that takes values in some set A such that
A is (totally) ordered; moreover, there are no infinite descending chains v0 > v1 > ... in A; and
for any recursive call, the variant decreases strictly."
But that didn't really help me that much. A more specific example would be great!
Suppose your recursive function makes a list of length n, in which all elements are zero.
This might look something like this:
fun foo 0 = []
| foo n = 0::(foo (n - 1))
In this case, the variant is the argument n to the function.
n is a natural number, and the natural numbers are totally ordered with no infinite descending chains, as no chain can go below zero.
Further, n decreases strictly with each recursive call.
Another example: Suppose your function takes in two arguments, x and y, and returns true if x > y and false otherwise.
fun bar 0 y = false
| bar x 0 = true
| bar x y = bar (x - 1) (y - 1)
In this case, there are several options for the variant. You could take it to be either x or y, as in the previous example, or to be x + y. In any of these cases, it takes on natural number values and strictly decreases.
Now, for an example where the arguments are nonintegers -- finding the sum of a list.
fun sum [] = 0
| sum (x::xs) = x + (sum xs)
In this case, the variant could be taken to be the length of the list (again a natural number), or to be the list itself, where lists are ordered as follows:
l1 < l2 iff there is some finite sequence of elements x1,x2,...,xn such that
x1::x2::...::xn::l1 = l2.
It is fairly easy to show that the set of lists is partially ordered, with no infinite descending chains, under this comparison, and, in particular, the set of lists generated by recursive calls starting from some list is totally ordered.
Further, in any recursive call, xs < (x::xs), by definition, so the list is decreasing.
The point of a variant is that it is a quantity that can be inducted over to prove things about the behaviour of a function. Since there are no infinite decreasing chains, there must be a minimum element, which can be taken as a base case for induction, and the total order then gives a way of inducting, from one element to the one immediately larger than it.
This can also be done with a partial order with no infinite decreasing chains, which guarantees that there are minimal elements, if not necessarily minimum elements. These can then be used as base cases, and a similar induction argument made, though likely with multiple ways of constructing larger elements.
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 ==.