Is there a way to put two actions as a result of then in the if - else statement? - sml

I want to make two results in if~~then~~.
For example,
fun count (x,[]) = 0
| count (x,y::ys) =
val cnt = 0
if x mod y = 0 then **/ cnt+1 and count(x,y/2) /**
else count (x-y,ys)
If the if statement is true, as in **/ /**, is there a way to make it do two things?

I want to make two results in if~~then~~ [...]
You can make a function that returns two results by using a tuple, e.g.:
(* Calculate the two solutions of a 2nd degree polynomial *)
fun poly (a, b, c) =
let val d = b*b - 4.0*a*c
val sqrt_d = Math.sqrt d
in ( (~b + sqrt_d) / (2.0*a), (~b - sqrt_d) / (2.0*a) )
end
And you can also deliver two different results depending on some criterion, e.g.:
fun poly (a, b, c) =
let val d = b*b - 4.0*a*c
val sqrt_d = Math.sqrt d
val root_1 = (~b + sqrt_d) / (2.0*a)
val root_2 = (~b - sqrt_d) / (2.0*a)
in
if root_1 > root_2
then (root_1, root_2)
else (root_2, root_1)
end
But if you need for a function to return one result in one situation, and two results in another situation, you need to wrap the result in a return type that can hold either one or two values, e.g.:
datatype ('a, 'b) one_or_two = One of 'a | Two of 'a * 'b
datatype item = Apple | Lamp | Knife
val gen = Random.newgen ()
fun loot () =
if Random.random gen > 0.90
then Two (Lamp, Knife)
else One Apple
You may also read the following StackOverflow Q&A: Multiple if statemens in one Function in SML

Related

Property Based Testing in F# using conditional parameters

I am currently writing a property based test to test a rate calculation function in f# with 4 float parameters, and all the parameters have specific conditions for them to be valid (for example, a > 0.0 && a < 1.0, and b > a). I do have a function checking if these conditions are met and returning a bool. My question is, in my test code using [Property>] in FsCheck.Xunit, how do I limit the generator to test the codes using only values meeting my specific conditions for the parameters?
If you are using FsCheck then you can use the Gen.filter function and the Gen.map function.
Lets say you have this function funToBeTested that you are testing, that requires that a < b:
let funToBeTested a b = if a < b then a + b else failwith "a should be less than b"
And you are testing the property that funToBeTested be proportional to the inputs:
let propertyTested a b = funToBeTested a b / 2. = funToBeTested (a / 2.) (b / 2.)
You also have a predicate that checks the condition requirements for a & b:
let predicate a b = a > 0.0 && a < 1.0 && b > a
We start by generating float numbers using Gen.choose and Gen.map, this way already produces values only from 0.0 to 1.0:
let genFloatFrom0To1 = Gen.choose (0, 10000) |> Gen.map (fun i -> float i / 10000.0 )
Then we generate two floats from 0 to 1 and filter them using the predicate function above
let genAB = Gen.two genFloatFrom0To1 |> Gen.filter (fun (a,b) -> predicate a b )
Now we need to create a new type TestData for using those values:
type TestData = TestData of float * float
and we map the resulting value to TestData
let genTest = genAB |> Gen.map TestData
Next we need to register genTest as the generator for TestData for that we create a new class with a static member of type Arbitrary<TestData>:
type MyGenerators =
static member TestData : Arbitrary<TestData> = genTest |> Arb.fromGen
Arb.register<MyGenerators>() |> ignore
finally we test the property using TestData as the input:
Check.Quick (fun (TestData(a, b)) -> propertyTested a b )
UPDATE:
An easy way to compose different generators is using gen Computation Expression:
type TestData = {
a : float
b : float
c : float
n : int
}
let genTest = gen {
let! a = genFloatFrom0To1
let! b = genFloatFrom0To1
let! c = genFloatFrom0To1
let! n = Gen.choose(0, 30)
return {
a = a
b = b
c = c
n = n
}
}
type MyGenerator =
static member TestData : Arbitrary<TestData> = genTest |> Arb.fromGen
Arb.register<MyGenerator>() |> ignore
let ``Test rate Calc`` a b c n =
let r = rCalc a b c
(float) r >= 0.0 && (float) r <= 1.0
Check.Quick (fun (testData:TestData) ->
``Test rate Calc``
testData.a
testData.b
testData.c
testData.n)
The answer by #AMieres is a great explanation of everything you need to solve this!
One minor addition is that using Gen.filter can be tricky if the predicate does not hold for a large number of elements that your generator produces, because then the generator needs to run for a long time until it finds sufficient number of valid elements.
In the example by #AMieres, it is fine, because the generator generates numbers in the right range already and so it only checks that the second one is larger, which will be the case for about half of the randomly generated pairs.
If you can write this so that you always generate valid values, then that's a bit better. My version for this particular case would be to use map to swap the numbers so that the smaller one is always first:
let genFloatFrom0To1 = Gen.choose (0, 10000) |> Gen.map (fun i -> float i / 10000.0 )
let genAB = Gen.two genFloatFrom0To1 |> Gen.map (fun (a, b) -> min a b, max a b)

Define nested functions in standard ml

I am new in sml. I tried to convert int to int list. For example, assume that there is an input 1234, then output is a list like [1,2,3,4]. And my question is, how can I type nested functions in sml? let in end? There is my code.
fun digit (a : int): int =
let
fun size (a) = if a < 0 then nil
else x = Int.toString x then digit s = size(x)
fun insert (num, nil) = [num]
| insert (num,xs) = x :: insert ()
fun convert (a, s) = if s < 0 then nil
else insert (a / (10*(s - 1)), xs)
then convert(a - (10*(s - 1), s - 1)
in
end
Nested functions are just one way to split up your workload in multiple, smaller parts. Another option is non-nested library functions. The main differences are that functions that aren't nested don't inherit its parent's variable scope, so they can only work with their own input, and functions that are nested aren't available anywhere else and can't be re-used. Let's say you're giving this problem a first stab:
fun digit_meh n = if n < 10 then [n] else n mod 10 :: digit_meh (n div 10)
And you realize it isn't doing exactly as you want:
- digit_meh 1234;
> val it = [4, 3, 2, 1] : int list
You could remove the most significant digit first, but the calculation isn't as trivial as n mod 10, since it depends on the number of digits.
You could generate this list and then reverse it:
fun digit n = rev (digit_meh n)
But the function digit_meh isn't particularly useful outside of this function, so it could be hidden using local-in-end or let-in-end:
local
fun digit_meh n = if n < 10 then [n] else n mod 10 :: digit_meh (n div 10)
in
val digit = rev o digit_meh
end
fun digit n =
let fun meh n = if n < 10 then [n] else n mod 10 :: meh (n div 10)
in rev (meh n) end
Do notice that the function meh's copy of n shadows digit's copy of n.
For clarity you could also name the variables differently.
Or you could look at how rev is doing its thing and do that. It basically treats its input as a stack and puts the top element in a new stack recursively so that the top becomes the bottom, much like StackOverflow's logo would look like if it jumped out and landed upside down like a slinky spring:
fun rev L =
let fun rev_stack [] result = result
| rev_stack (x::xs) result = rev_stack xs (x::result)
in rev_stack L [] end
Because the result is accumulated in an additional argument, and rev should only take a single argument, nesting a function with an extra accumulating argument is a really useful trick.
You can mimic this behavior, too:
fun digit N =
let fun digit_stack n result =
if n < 10
then n::result
else digit_stack (n div 10) (n mod 10::result)
in f N [] end
This way, we continue to treat the least significant digit first, but we put it in the stack result which means it ends up at the bottom / end. So we don't need to call rev and save that iteration of the list.
In practice, you don't have to hide helper functions using either local-in-end or let-in-end; while it can be useful in the case of let-in-end to inherit a parent function's scope, it is not necessary to hide your functions once you start using modules with opaque signatures (the :> operator):
signature DIGIT =
sig
val digit : int -> int list
end
structure Digit :> DIGIT =
struct
fun digit_stack n result =
if n < 10
then n::result
else digit_stack (n div 10) (n mod 10::result)
fun digit n = digit_stack n []
end
As this is entered into a REPL, only the relevant function is available outside of the module:
> structure Digit : {val digit : int -> int list}
signature DIGIT = {val digit : int -> int list}
- Digit.digit 1234;
> val it = [1, 2, 3, 4] : int list
fun aFunctionCallingF2F3 someVariables =
let
<define some functions and local variables here>
fun F2 ...
fun F3 ...
val v1 ...
val v2 ...
in
<Make use of the functions/variables you defined above and `someVariables`>
end
For example,
fun areaCirle r:real =
let fun square x:real = x*x
val pi = 3.14
in
pi * square r
end
Or define functions you need to call beforehand if they are not mutually recursive. If they are mutually recursive, you can look up the keyword and.
fun F2 ...
fun F3 ...
fun aFunctionCallingF2F3 = <make use of F2 F3 directly>
For example,
fun square x:real = x * x
fun areaCircle r = square r * 3.14
Note that you cannot do
fun areaCircle r = square r * 3.14
fun square x:real = x * x
square needs to be defined before areaCircle.

tuple access: Can't find a fixed record type

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;

Checking whether a given value exists in a binary tree

I am new to SML. I am trying to check whether a given value exist in the binary tree or not. Below is the snippet of the code. Upon execution it gives
Warning : match nonexhaustive (n,Node (t1, j, t2)) => ...
I cannot understand why it is showing this way. I guess I have covered all possible case. Can anyone give me hint or link which will be helpful to remove this warning.
datatype inttree = Empty | Node of inttree * int * inttree;
(*find(n,K) here n is the key that we have to find in inttree K*)
val rec find = fn(n, Node(t1,j,t2)) =>
let
val t = Node(t1, j, t2)
val compare = fn(i,j) => i = j
val find' =
fn (n,Empty) => false (* if we have reached the empty node then we are not able to find the key therefore return false *)
| (n,Node(t1,j,t2)) =>
if compare(n,j)
then true (* if value n and j are equal we have found the key n in the tree*)
else find(n,t1) orelse find(n,t2) (* if the value is not equal check in left subtree if found return true else check in the right subtree*)
in
find'(n,t)
end;
Given your datatype declaration, a fairly direct recursive approach is possible. Since this seems to be homework, I don't want to give a complete solution, but here is a function which has a similar flavor:
fun allEven Empty = true
| allEven (Node(t1,i,t2)) =
if i mod 2 = 1 then false
else allEven t1 andalso allEven t2;
This function returns true or false depending on whether or not all integers in the tree are even. It has a basis case
allEven Empty = true
(true since there are no odd numbers in an empty tree to serve as counter-examples) and a recursive case
allEven (Node(t1,i,t2)) =
if i mod 2 = 1 then false
else allEven t1 andalso allEven t2;
If the integer at the node is odd, return false -- otherwise return true if the recursive call to both branches evaluate to true.
Typical runs:
- allEven (Node(Node(Empty,3,Empty),5,Node(Node(Empty,6,Empty),7,Empty)));
val it = false : bool
- allEven (Node(Node(Empty,4,Empty),2,Node(Node(Empty,6,Empty),8,Empty)));
val it = true : bool
Your function should be about this long and follow the same basic recursive pattern.
Besides val rec, you can also write fun and specify the arguments on the left-hand side of the =.
The helper function compare is largely redundant. You might as well use =. Also, what one would call a compare function in ML is usually one that returns the type order, having the values LESS, EQUALS and GREATER:
- ​Int.compare (3, 5);
> val it = LESS : order
When writing an if ... then true else ... or similar statement that returns the type bool, you might as well just use the combinators orelse and andalso. For example, you can replace the following:
if compare(n,j)
then true
else find(n,t1) orelse find(n,t2)
with:
n = j orelse find (n, t1) orelse find (n, t2)
Much like the built-in functions List.exists and List.all take a function as predicate and scans a list in the attempt to prove either that at least one element exists for which this is true, or that it is true for all elements, you can make functions treeExists and treeForall:
datatype intTree = Empty | Node of inttree * int * inttree;
fun treeExists f Empty = false
| treeExists f (Node (leftTree, x, rightTree)) =
f x orelse treeExists f leftTree orelse treeExists f rightTree
fun treeForall f Empty = true
| treeForall f (Node (leftTree, x, rightTree)) =
f x andalso treeForall f leftTree andalso treeExists f rightTree
Making functions find and allEven has now become simpler:
fun find (x, tree) = treeExists (fn y => x = y) tree
fun allEven tree = treeForall (fn x => x mod 2 = 0) tree
since all the recursion has been left to new library functions.
In a similar way, you can make treeMap and treeFold:
fun treeMap f Empty = Empty
| treeMap f (Node (leftTree, x, rightTree)) = ...
fun treeFold f e Empty = e
| treeFold f e (Node (leftTree, x, rightTree)) = ...
They could be used to find the largest absolute value in a tree:
fun maxAbsTree tree =
treeFold Int.max 0 (treeMap Int.abs tree)

convert a few 2-tuples to a list of lists

this is a question about ocaml lists and tuples. I have some 2-tuples of numbers (either integers or floats) and I want to convert it to a list of lists (with 2 elements). Assuming that I have defined a num type Int of int | Float of float, the conversion should give the following:
((1,1.0),(0.4,1),(0,0)) => [[Int 1;Float 1.0];[Float 0.4; Int 1];[Int 0;Int 0]]
or more precisely
let a = (1,1.0) and b = (0.4,1) and c = (0,0) in
myconversion (a,b,c) ;;
=> [[Int 1;Float 1.0];[Float 0.4; Int 1];[Int 0;Int 0]]
the point being the values a, b, c... are defined in several places in the source files (by people who use different signatures for their tuples).
The difficulty here is that I don't know the types of the elements of the 2-tuples (int or float, that varies depending on the tuple).
Your input data can't be represented in OCaml as you describe it. OCaml is strongly typed. For example, your example input list is an invalid value in OCaml:
# [(1,1.0);(0.4,1);(0,0)];;
Error: This expression has type float but an expression was expected of type
int
So what you describe as the essence of your problem (not knowing the types) is in fact not possible. You'll have to use some other method of representing the input. For example, you could just use floats for everything. Or you could use pairs of strings.
Update
The answer for the rewritten question is the same. In OCaml it's not possible not to know the type of something statically; i.e., at the time you're writing the program (unless it can be any type at all). It's not possible (or necessary) to query the type of something at runtime. So your question doesn't have an answer (at least as far as I can see).
For OCaml, you have to think with the type system rather than against it. After a while you start to really like it (or at least that's how it worked for me). I'd start by writing down the type you want your function myconverstion to have.
Update 2
I'll repeat my advice to treat your inputs as strings. Assuming you've parsed your input up into pairs of strings, here's some code that does what you want:
let myconversion coords =
let c1 s =
if String.contains s '.' then
Float (float_of_string s)
else
Int (int_of_string s)
in
let cp (a, b) = [c1 a; c1 b] in
List.map cp coords
Here's how it works for your input (reinterpreted as strings):
# myconversion [("1", "1.0"); ("0.4", "1"); ("0", "0")];;
- : fi list list = [[Int 1; Float 1.]; [Float 0.4; Int 1]; [Int 0; Int 0]]
Update 3
Here's some (crude) code that parses a file of numbers into coordinates represented as pairs of strings. It should work as long as the tuples in the input are well formed.
let coords fname =
let ic = open_in fname in
let len = in_channel_length ic in
let buf = Buffer.create 128 in
let () = Buffer.add_channel buf ic len in
let () = close_in ic in
let s = Buffer.contents buf in
let nums = Str.(split (regexp "[^0-9.]+") s) in
let rec mkcoords sofar = function
| [] | [_] -> List.rev sofar
| a :: b :: rest -> mkcoords ((a, b) :: sofar) rest
in
mkcoords [] nums
There are two distinct problems in your setup:
you don't know the type of the tuples parameters
you want to pass them as a single n-ary tuple
For problem 2, you would have to write a function for that type specifically, whereas you could mimic a type level list type by nesting couple of tuples:
myconversion a,(b,c) ;;
The reason is that with that setup, you could write a recursive polymorphic function on the type level list:
val myconversion : type a b. (a,b) -> num list
There would still be a problem on the last element though.
So, assuming that you could pass a sequence to your conversion function, and have it process elements of that sequence one by one, you would still need to find a way of selecting the proper function of pair conversion from the tuple type: that's basically ad-hoc polymorphism, ie. you would need to be able to overload a function on its parameters' types(1). Unfortunately, OCaml doesn't support that out of the box.
One possibility would be perhaps (I have no experience doing that) to implement an extension which would extract the type information of a given expression, and generate the correct code to process it in your own code.
A flexible technique consists in having that extension generate an algebraic description of the tuples types, and use that description as an equality witness in the code which will process the tuples:
type _ w =
| U : (unit * unit) w
| IF : 'a w -> ((int * float) * 'a) w
| FI : 'a w -> ((float * int) * 'a) w
(* other constructors if necessary *)
(* data *)
let a = 1,1.0
let b = 2.0, 2
let c = 3.0, 3
let d = 4, 4.0
let l = a,(b, (c,(d,((),()))))
(* witness *)
let w = IF (FI (FI (IF U)))
(* the type parameter of w should be the same as l type *)
let rec conv : type a b. (a * b) w -> (a * b) -> num list = fun w (x, xs) ->
match w with
U -> []
| IF w' -> let i,f = x in (Int I)::(Float f)::(conv w' xs)
(* etc *)
Here, we encode the type level nil list as (unit * unit) w.
A coalgebraic approach would require to register function overloads to the conversion function polymorphic signature within the extension, and let it pick the right one from the function overload dictionary.
There's a discussion on that topic on the LtU site.
Thanks to everybody who answered. I finally found a solution, using a bit of magic:
# type num = Int of int | Float of float;;
# let to_num x = if Obj.is_int (Obj.repr x) then
Int (Obj.magic (Obj.repr x) : int)
else
Float ((Obj.magic (Obj.repr x) : float));;
# let pair_to_num (a,b) = [to_num a; to_num b];;
# let myconversion (a,b,c) = [pair_to_num a; pair_to_num b; pair_to_num c];;
and the test:
# myconversion ((1,1.0),(0.4,1),(0,0));;
- : num list list = [[Int 1; Float 1.]; [Float 0.4; Int 1]; [Int 0; Int 0]]
# myconversion ((0,0),(1,1.0),(0.4,1));;
- : num list list = [[Int 0; Int 0]; [Int 1; Float 1.]; [Float 0.4; Int 1]]
Magic, the order does not matter and the type is recorded! I can then follow didier's idea to get rid of the pair of superfluous parentheses.