Floating-point number operations in OCaml [duplicate] - ocaml

This question already has an answer here:
Unary minus and floating point number in OCaml
(1 answer)
Closed 4 years ago.
I am trying write a function that takes as input a list of floating point numbers
and returns a list in which all negative numbers are removed from the input list and then all resulting positive numbers are negated.
let f (mylist: float list) : float list =
let f1 = List.filter (fun x -> x < 0.0) mylist in
List.map (fun x -> (-x*1.0)) f1
I have a type error:
Error: This expression has type float but an expression was expected of type int
Why is that?
Thank you.

I figured this out.
For the last time, to negate a floating-point number, the appropriate operator is:
(-.x)

Related

Using foldr and a lambda expression as its first argument [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm trying to figure out how to use lambda expressions and I saw that they're commonly used in functions such as foldl or foldr.
I'm wondering why the following code doesn't work:
ExMin = foldr (\x y -> x < y) 5 [1,2,3,4]
I want this function to give me the minimum number in the list, however it gives error.
I'm thinking that the reason it errors is because x < y returns a boolean, and what I'm expecting from it is an integer.
Any ideas on how I can make it return the number correctly?
I'm wondering why the following code doesn't work:
ExMin = foldr (\x y -> x < y) 5 [1,2,3,4]
Because a foldr function takes a folding function with type a -> b -> b where b is the type of the "accumulator", a value that is passed right-to-left and each time is taken as input to the fold function and another element. Eventual foldr returns the final value for the accumulator.
Any ideas on how I can make it return the number correctly?
Yes, you can use the min :: Ord a => a -> a -> a function. This will each time return the minimum of the accumulator and an element:
ExMin = foldr min 5 [1,2,3,4]
As #amalloy says you can not use variables that start with an Uppercase, this should be a lowercase:
exMin = foldr min 5 [1,2,3,4]

SML Error: operator and operand don't agree [tycon mismatch]

I'm new to SML and don't quite understand my issue, although I'm certain I'm at fault. First off, here are two short functions I am testing and their descriptions.
MakeInterval - Takes a natural number r, (also used for rp) and a natural number t, and returns the interval [t-r,t+r].
fun MakeInterval(r,rp,t) =
if r + rp < 0 then []
else t-r :: MakeInterval(r-1,rp,t);
E.g. MakeInterval(3,3,10) will return [7,8,9,10,11,12,13]. If you have a suggestion for getting rid of rp, please let me know. It's the only way I could think of to keep track of the original value of r while maintaining sorted order.
NotDivisible - Takes a natural number r, a list of natural numbers ts1 and another list of natural numbers ts2. Code using ts2 isn't yet written.
r specifies the lower and upper bounds of the interval, (same as MakeInterval), and ts1 is a list of numbers to be fed into map with the MakeInterval function.
fun NotDivisible(r, ts1, ts2) =
map (fn x => MakeInterval(r,r,x), ts1);
This function should return a list of intervals. E.g. NotDivisible(3, [10,20,30],
[2,4,6]) will return (for now) [[7..13], [17..23], [27..33]].
After I get this working, I will begin manipulating these lists to find which numbers out of these intervals are indivisible by any of the numbers in ts2.
But for now, my issue lies with the function definitions as I have them. MakeInterval is defined with no issues and I have tested it on it's own. This is the error I receive when attempting to define NotDivisible:
stdIn:5.33-5.71 Error: operator and operand don't agree [tycon mismatch]
operator domain: 'Z -> 'Y
operand: (int -> int list) * 'X
in expression:
map ((fn x => MakeInterval <exp>),ts1)
I've tried specifying all types manually to no avail. Everything makes sense to me logically, but clearly there is a syntax issue here that I am not following.
The issue with the above is the invocation of map, the function is curried
map : ('a -> 'b) -> 'a list -> 'b list;
so, a small change to the parentheses:
fun NotDivisible(r, ts1, ts2) = map (fn x => MakeInterval(r,r,x)) ts1;
gives you:
val NotDivisible = fn : int * int list * 'a -> int list list

operator and operand don't agree [equality type required]

This function calculate count element y in list
fun func y xs=List.length(List.filter(fn x => x=y) xs);
val countElement = fn : ''a -> ''a ?.list -> int
func 1 [1,2,3,4];
val it = 1 : int
But, when I write func 1.1 [1.1,2.1,3.1,4.1]; I get error:
stdIn:64.1-64.35 Error: operator and operand don't agree [equality type required]
operator domain: ''Z
operand: real
in expression:
countElement 1.1
How can I solve it problem ?
real is not an equality type in SML 97. That means you cannot use = to compare two reals.
Standard ML has a concept of "equality types", or types that "admit equality"; or, more to the point, it has a concept of types that do not admit equality. You can only use = on types that do admit equality. (This is why its type is ''a * ''a -> bool rather than 'a * 'a -> bool. Type variables that start with '' can only be instantiated to equality types.)
In SML '97, real is one type that does not admit equality; so, the following code will not type-check:
val oneIsOne = (1.0 = 1.0) (* FAIL! *)
The reason for this design decision is that IEEE 754 (the standard that defines floating-point numbers) defines "equality" in a rather strange way — NaN is not equal to itself, and 0.0 is equal to ~0.0 even though 1 / 0.0 is not equal to 1 / ~0.0. The language designers decided that they didn't want = to differ from the semantics specified by IEEE 754, but that they also didn't want the semantics of = to be different for real than for all other types in the language. Instead, they completely eliminated = for real, and made the IEEE 754 definition semantics available as Real.== [link]. So, you can write:
fun countRealElement y xs = List.length (List.filter (fn x => Real.== (x,y)) xs)
val it = countRealElement 1.1 [1.1,2.1,3.1,4.1] (* 1 *)
(where countRealElement has type real -> real list -> int).

subtract functions with type real in ml

I'm trying to subtract two functions(both with type real) in moscow ml. It then says "Overloaded - cannot be applied to arguments of type real -> real. So how should I write the function?
fun CircleArea x = x*x*Math.pi
fun SquareArea x:real = 4*x*x
fun Area x = SquareArea - CircleArea
You probably don't actually want to subtract one function from another, but the return values of those functions once they are applied. You could achieve this in the following way:
fun Area x = (SquareArea x) - (CircleArea x)
The parentheses are not mandatory, since function application (i.e. the space between SquareArea and x) binds tighter than any binary operator, including -.
You should consider using the following naming convention in ML: Regular functions have a lowercase starting symbol, while value constructors for algebraic types have uppercase starting symbols. For example:
fun area x = squareArea x - circleArea x
But:
datatype shape = Square of int * int
| Circle of int
Subtraction of functions like we have in mathematics isn't provided as a built-in operator. You can, however, define your own.
Mathematically speaking, we define
(f - g)(x) = f(x) - g(x)
We can replicate this definition in SML as follows:
infix 5 --
fun f -- g = fn x => f x - g x
What this does is produce an operator, --, such that f -- g produces the function corresponding to fn x => f x - g x, i.e. the function that given an x calculates f x - g x.
Note, due to the type-ambiguity in the - operator, it'll default to let you subtract 'a -> int functions. In your case you'll want to subtract 'a -> real functions, so you'll need a slight modification:
infix 5 --
fun f -- g = fn x => f x - g x : real
If you use this ---operator, you will be able to define your Area function like so:
val area = squareArea -- circleArea;
(I took the liberty of making the first letter of function names lowercase, to match the SML naming conventions.)

OCaml: List mapping a function with 2 inputs

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