I want to assign multiple values within the function, say in the function:
fun posdiv(n,l::ls)=let val m=n in posdiv1(k,m,n,l::ls) end;
I want to a let val... like below:
fun posdiv(n,l::ls)=let val m=n (*and val j=greatest(l::ls) where greatest is a different function and returns a value not a list*)in posdiv1(k,m,n,l::ls) end;
What is the general syntax for it?
Same syntax as assigning multiple values in other places:
fun posdiv (n, l::ls) =
let
val m = n
val j = greatest (l::ls)
in
posdiv1 (k, m, n, l::ls)
end
Related
Im trying to add a tuple of type (int*int) on a for cycle to a list but i get an error saying : this expression should have type unit.
this is what i have right now:
let addtuple k lst =
for i=0 to k - 1 do
let (n,j) =Scanf.scanf " %d %d" (fun a b->(a,b))
in
(n,j)::lst
done;;
The purpose of the OCaml for is to do something, rather than compute a value. So the body of the loop should be an OCaml expression that has a useful side effect (like printing a value). For this reason, the body of a for loop should have the type unit, the type used for expressions that don't have an interesting value. But your loop has a body that is a list. The compiler is telling you (correctly) that this indicates that something is wrong.
Your code is written assuming that the expression (n, j) :: lst will change the value of lst. But this is not the case. In a functional language like OCaml, you can't change the values of variables.
If your function is supposed to return a list, it can't be based on a for loop, which always returns () (the unique value of type unit). Most likely it should be based on a fold (which accumulates a value while working through a series of inputs) or on your own recursive function.
With a for you need to use ref:
let addtuple k lst =
let r = ref lst in
for i = 1 to k do
r := (Scanf.scanf " %d %d" (fun x y -> (x, y))) :: !r
done;
!r;;
A more functional approach using a recursive function:
let rec addtuple k lst =
match k with
| 0 -> lst
| _ -> addtuple (k - 1) ((Scanf.scanf " %d %d" (fun x y -> (x, y))) :: lst);;
The problem says:
Write a function that returns all the subsets with k elements from a given set.
I managed to write a code to extract all the subsets from a set:
module Int = struct
type t = int
let compare = compare
end
module IS = Set.Make(Int)
module IIS = Set.Make(IS)
let addelement e ps = IIS.fold (fun s r -> IIS.add (IS.add e s) r) ps ps;;
let powset s = IS.fold addelement s (IIS.singleton IS.empty);;
let set = IS.of_list [1;2;3];;
let r = powset set;;
List.map IS.elements (IIS.elements r);;
Now the only thing that I have to do is to implement the condition so that every subset we get from the set needs to have exactly k elements. How do I do that?
You can do this easily on the latest result you get by using List.filter , you could extract the elements that have a given number of elements.
List.filter (fun x -> List.length x = k) (List.map ...);;
I wrote a function that is supposed to receive a list of tuples. I access the components of the tuples with # and the code compiles:
fun recheck ([], n) = []
| recheck (h::t, n) =
if ((#1 h) * (#1 h)) + ((#2 h) * (#2 h)) = n then
h::recheck(t, n)
else
recheck(t, n)
But another function that basically does the same thing, namely receiving a list of tuples and accessing those, causes an error.
fun validate ([]) = true
| validate (h::t) =
if 1 = (#1 h) then
true
else
false
Can't find a fixed record type. Found near #1
What is the difference here and why does the latter cause an error?
Edit
The first function actually does not compile on its own.
But this entire snippet does:
fun drop ([], n) = []
| drop (h::t, 0) = h::t
| drop (h::t, n) =
drop(t, n-1)
fun sts_linear (y, n) =
if y < (Math.sqrt(n)+1.0) then
let
(* x^2 + y^2 = n => x = sqrt(n-y^2) *)
val x = Math.sqrt(n - (y * y));
val xr = Real.realRound(x);
in
if (abs(x - xr) < 0.000000001) then
[(Real.trunc xr, Real.trunc y)]#sts_linear (y+1.0, n)
else
(
[]#sts_linear (y+1.0, n)
)
end
else []
fun recheck ([], n) = []
| recheck (h::t, n) =
if ((#1 h) * (#1 h)) + ((#2 h) * (#2 h)) = n then
h::recheck(t, n)
else
recheck(t, n)
fun sts (n) =
(
let
val pairs = sts_linear(0.0, Real.fromInt n);
in
recheck(drop(pairs, Real.ceil( Real.fromInt (length(pairs))/2.0 ) ), n)
end
)
Your first code doesn't compile, at least with SML/NJ:
If you got it to compile then it must have been in a nonstandard extension of SML.
The problem with both of your definitions is that there is no polymorphic idea of a tuple of arbitrary arity in SML. You can write functions to work on lists of pairs. You can write functions to work on lists of triples. But -- you can't write functions to work simultaneously on lists of pairs and lists of triples (at least if your function tries to do things with these pairs/triples as tuples).
One solution is to get rid of # and use pattern-matching to extract the components:
fun validate [] = true
| validate ((x,y)::t) =
if x = 1 then
true
else
false
But, if you really want to write a function which can polymorphically apply to either lists of pairs or list of triples (or quadruples,...), the easiest thing to do is to represent the pairs, triples, etc. as lists rather than tuples. Lists which contains lists of nonspecified size are not a problem in SML.
Trying to minimize this down, as I have seen the following work in SML/NJ
and i'm not aware of it actually being a compiler extension
val p1 = {x=0, y=0};
val p2 = {x=1, y=1};
val p3 = {x=1, y=1, z=1};
There is an awkward construct from a compiler error perspective
not many languages have errors that work in this fashion,
because the function is valid, but produces a type error
unless an invocation of the function exists to resolve the
type of 'record', thus to resolve the error more code must be added.
fun getFoo(field) = fn record => field record;
Without the following actual calling of the getX
the compiler cannot determine the type of record
of which the complete type information of ALL fields
of the record must be known to the compiler, not just the #x field.
let val getX = getFoo(#x);
val x1 = getX(p1);
val x2 = getX(p2);
val x3 = getFoo(#x)(p3);
in () end;
while the following commented out snippet results in an error because the types of
p1 and p3 are different, and so different invocations of getFoo
are required
(*
let val getX = getFoo(#x);
val x1 = getX(p1);
val x3 = getX(p3);
in () end;
*)
and the following is insufficient since it never resolves the record.
let val getX = getFoo(#x) in () end;
I am trying to figure out how to implement the fold functions on inputs of differing types. As a sample, I'll use the count function for a list (though, I have multiple functions to implement for this).
Assuming an int list input (this should work with any type of list, though), my count function would be
val count = foldr (fn(x:int,y)=>y+1) 0 ;
val count = fn : int list -> int
However, I am attempting to make a count function where the type is
val count = fn : int list * bool list -> int
where the int list is the universe of the set, and the bool determines which values of the universe are in the set. ie, (1,3,5,6),(true,false,false,true) results in a final set of (1,6), which would have a count of 2. My first thought to try this was some form of
val count= foldr (fn(x:(int*bool),y)=>if #2x then y+1 else y ) 0 ;
but this results in a return type of
val count = fn : (int * bool) list -> int
which is not quite what I need. Logically, they are similar, but I am expected to group the two types together in one list each.
You could use ListPair.foldl:
fun count (xs, bs) = ListPair.foldl (fn (x, b, acc) => ...) ... (xs, bs)
where the first ... is some combination of x, b and acc and the second ... is the initial value.
This assumes that xs and bs are equally long, and in case they're not, discards the remaining elements in the longer list. (You should probably try to justify if this gives the correct answer in either case xs or bs is longer.)
Otherwise, you need to combine (aka zip) your int list × bool list into an (int × bool) list by making a function that combines two lists, and use this function in combination with the folding you are already doing.
fun combine (x::xs, y::ys) = ...
| combine (..., ...) = ...
This function could be equivalent to ListPair.zip.
I have this problem:
I have a list with let say [2;1;2;1;4;1] and a int, I want to add the integer number to a new list if it accours in the first list, that means that the result should be a new list with [1;1;1] if the integer is 1, I believe i can use tail-recursion and I have used google and looked for something similar here at stackoverflow but I can't find it.
I suggest you take a look at the built-in higher-order functions:
[2; 1; 2; 1; 4; 1] |> List.filter (fun e -> e <= 1)
This is tail-recursive for you already!
let findOccurences e = List.filter ((=) e)