Recursion In simple ML Standard - functional-programming

fun max (xs : int list)=
if null xs
then NONE
else
let val tl_ans = max(tl xs)
in
if isSome tl_ans andalso valOf tl_ans > hd xs
then
tl_ans
else
SOME (hd xs)
end
I can't figure how this program works from my understanding:
we enter the else then we call max(tl xs) recursively till it hit none so when we have none we check the if in the in and it will be false then we return SOME(hd xs).
the question will be that I can't understand how this program works line by line I feel that I missed something.

I suspect the mistake you're making is trying to reason about several recursions at once.
Focus at just one function call at a time.
Example:
max [] is NONE, as you say.
Next, take max [2] as an example.
This is
let val tl_ans = max []
in
if isSome tl_ans andalso valOf tl_ans > 2
then
tl_ans
else
SOME 2
end
which is
if isSome NONE andalso valOf NONE > 2
then
NONE
else
SOME 2
which is clearly SOME 2.
Next, try max [3,2]
This is
let val tl_ans = max [2]
in
if isSome tl_ans andalso valOf tl_ans > 3
then
tl_ans
else
SOME 3
end
and you know that max [2] is SOME 2, so this is
if isSome (SOME 2) andalso valOf (SOME 2) > 3
then
SOME 2
else
SOME 3
which is SOME 3.
And so on...

Related

is the execution of the same function twice worse than associating the result to a variable?

I was told that this first piece of code is, in terms of performance, worse than the second.
But, I honestly cannot figure out how they can be different, if in the end the same calls are made.
Am I missing something?
First example with explicit calls:
#let rec max l =
match l with
x::[]->x
| x::xs -> if(x > max xs)
then x else max xs;;
Second example with variable usage:
#let rec max l =
match l with
x::[]->x
| x::xs -> let m = max xs
in
if (x>m) then x else m;;
The key is that the ocaml compiler does not know that max xs and max xs are the same thing, so your first example is equivalent to something like:
let rec max l =
match l with
| x::[]-> x
| x::xs ->
let m1 = max xs in (* first call *)
if (x > m1) then
x
else
let m2 = max xs in
m2 (* second call *)
;;
Making only one call is a valid optimization, but is not correct in the general cases. For example:
let f () =
print_endline "hello";
print_endline "hello";
3
is not equivalent to:
let g () =
let x = print_endline "hello" in
x;
x;
3

how to split a list into two lists in which the first has the positive entries and the second has non-positive entries-SML

I am a new to SML and I want to write a function splitup : int list -> int list * int list that given a list of integers creates from two lists of integers, one containing the non-negative entries, the other containing the negative entries.
Here is my code :
fun splitup (xs :int list) =
if null xs
then ([],[])
else if hd xs < 0
then hd xs :: #1 splitup( tl xs)
else hd xs :: #2 splitup( tl xs)
Here's the warning i get:
ERROR : operator and operand don't agree
ERROR : types of if branches do not agree
The function splitup(tl xs) should return int list * int list so i think my recursion should be all right.
What is the problem and how can i fix it ?
The problem is that
hd xs :: #1 splitup( tl xs)
and
hd xs :: #2 splitup( tl xs)
are lists – you can tell from the :: – not pairs of lists as the result should be.
For the non-empty case, you need to first split the rest of the list, then attach the head to the correct part of the result and add it the other part of the result in a pair.
It's also a good idea to get used to pattern matching, as it simplifies code lot.
Something like this:
fun splitup [] = ([], [])
| splitup (x::xs) = let (negatives, non_negatives) = splitup xs
in if x < 0
then (x :: negatives, non_negatives)
else (negatives, x :: non_negatives)
end
There is already List.partition: ('a -> bool) -> 'a list -> 'a list * 'a list, a higher-order library function that does this. In case you want to split up integers into (negative, non-negative):
val splitup = List.partition (fn x => x < 0)

foldr/foldl with logic operators in SML

I'm trying to build a function in SML using foldr or foldl that will return the logic or and logic and of all elements in a list.
I've tried in this way, using and and or:
fun band x = foldr (op and) true x;
fun bor x = foldr (op or) false x;
And also using andalso and orelse. But I keep receiving error messages such as:
Error: unbound variable or constructor: or
(Answer instead of comment.) Consider using List.all : ('a -> bool) -> 'a list -> bool and List.exists : ('a -> bool) -> 'a list -> bool since they're short-circuiting, unlike List.foldl. There is really no point in folding farther than the first false in band's case, or true in bor's case. That is,
val band = List.all (fn b => b)
val bor = List.exists (fn b => b)
One definition for these library functions is found here:
fun all p [] = true
| all p (x::xr) = p x andalso all p xr;
fun exists p [] = false
| exists p (x::xr) = p x orelse exists p xr;
Since the list being fed to band and bor are already of type bool, passing the identity function (fn b => b) will produce the desired truth value. The functions are generic enough to work on any kind of list for which you can apply a predicate for each element, so if you were generating your bool list from some other list, you could avoid that step.
I've found out the problem: andalso and orelse are not operators nor functions cause they implement a short-circuit evaluation.
Therefore, the solution should be:
fun band x = foldl (fn (a,b) => a andalso b) true x;
fun bor x = foldr (fn (a,b) => a orelse b) false x;
There are no operators called and and or in SML. and is a keyword to separate multiple variable or declarations that are declared at the same time. There is no or.
The AND and OR logical operators are andalso and orelse which as you said in your own answer are short-circuiting, and not regular operators.

How does let work in this function?

This function finds the max number of a list and im having difficulty understanding it :
fun max1 (xs : int list) =
if null xs
then NONE
else
let val tl_ans = max1(tl xs)
in
if isSome tl_ans andalso valOf tl_ans > hd xs
then
tl_ans
else
SOME (hd xs)
end;
How is tl_ans being computed in line if isSome tl_ans andalso valOf tl_ans > hd xs
since it has not been set yet ?
The function has two cases:
1) Base case - List is empty
There is no maximum, return NONE
2) List is not empty - Since the list is not empty, the list will have a head (the first element) and a tail (all elements except the first). Note that the tail will be empty for a list with one element.
The idea here is that for non-empty lists, calculate the maximum for the tail of the list recursively, tl_ans ("tail answer" or maximum among the tail) in your function. Since we know the maximum among all the elements except the first element (the head), now the maximum of the whole list is just the maximum among tl_ans and head of the list.
On each recursive call, the input size is reduced by 1 because we are just passing the tail of the list (that is, without first element). This would finally call the base case when it has got a list with only one element for which the tail is empty. From there, on it's way back from each recursive call, the head for that recursive call would be compared with what returned from the recursion.
Here is an illustration:
max [5,2,6,4]
tl_ans = max [2,6,4], hd = 5
|
|=>tl_ans = max [6,4], hd = 2
|
|=>tl_ans = max [4], hd = 6
|
|=>tl_ans = max [], hd = 4
|
|<= None (Base case)
<= Some 4, comparing tl_ans (None) and hd (4)
<== Some 6, comparing tl_ans (Some 4) and hd (6)
<= Some 6, comparing tl_ans (Some 6) and hd (2)
<= Some 6, comparing tl_ans (some 6) and hd (5)
The lines
let val tl_ans = max1(tl xs)
in
if isSome tl_ans andalso valOf tl_ans > hd xs
mean let the value of tl_ans be max1 (tl xs) in the following code.
(You usually say that the value of max1 (tl xs) is bound to the name (or variable) "tl_ans".)
It means exactly the same as
if isSome (max1 (tl xs)) andalso valOf (max1 (tl xs)) > hd xs
except that the value max1 (tl xs) is only computed once.
This is not the most idiomatic way to write such a function in Standard ML. Writing it in another way, I propose, will give a better understanding of how it works. The functions valOf, hd and tl are so-called partial functions and the only excuse for using them is when assuring that their input is not NONE or [] respectively (in which case the program will invoke an exception).
Using valOf, hd or tail will thus require you to check if a list is empty (e.g. null xs) or an option exists (e.g. isSome ans), and so the convenience of using it is limited. Instead, using pattern matching (or more robust versions of those functions) is desired.
Below I have written the same function in two other ways, one of which resembles the one you supply.
(* For a list with at least one element in it, check to see if there is a
* greatest element in the tail (xs). If there isn't, then x is the greatest
* element. Otherwise, whichever is the greatest of x and y is the greatest.
*
* This solution is comparable to the one you have above: Find a solution
* for the "smaller" problem (i.e. the reduced list in which x isn't in),
* and then combine the solution. This means making a recursive call to a
* function that doesn't exist at the time of writing it. *)
fun max [] = NONE
| max (x::xs) =
(case max xs of
NONE => SOME x
| SOME y => SOME (Int.max (x, y)))
(* If we were to use a let-expression instead of a case-of, but still restrict
* ourselves from using partial functions, we might make a helper function: *)
fun maxOpt (x, NONE) = SOME x
| maxOpt (x, SOME y) = SOME (Int.max (x, y))
(* Now the essence of the let-expression is boiled down: It finds the largest
* value in the tail, xs, and if it exists, finds the largest of that and x,
* and pass it as a result packed in SOME. *)
fun max [] = NONE
| max (x::xs) =
let val y_opt = max xs
in maxOpt (x, y_opt) end
(* In fact, one can store the largest value so far in the front of the list.
* This is only because the return type is int option, and the input type is
* int list. If the return type were dramatically different, it might not be
* so easy. *)
fun max [] = NONE
| max (x::y::xs) = max (Int.max (x,y)::xs)
| max [x] = SOME x

Summation in functional programming

I was searching in the web for exclusion-Inclusion principle, what i have found is this:
(from MathWorld - A Wolfram Web Resource: wolfram.com)
http://mathworld.wolfram.com/Inclusion-ExclusionPrinciple.html
I doesn't matter if you don't understand the formula, in fact, what i need is to implement this:
For example, the input is:
(summation (list 1 2) 3)
Where (list 1 2) is i and j and 3 is the limit of the sum n.
(n had to be up the sigma but...)
Then, the output of formula, in Scheme will be:
(list (list 1 2) (list 1 3) (list 2 3))
How can i implemment this in Scheme or in Haskell? (sorry for my English).
In Haskell, use a list comprehension:
Prelude> [(i,j) | i <- [1..4], j <- [i+1..4]]
[(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)]
Prelude> [i * j | i <- [1..4], j <- [i+1..4]]
[2,3,4,6,8,12]
Prelude> sum [i * j | i <- [1..4], j <- [i+1..4]]
35
First line gives all a list of all pairs (i,j) where 1 <= i < j <= 4
Second line gives a list of i*j where 1 <= i < j <= 4
Third line gives sum of these values: Σ1 <= i < j <= 4 i*j.
In racket, you'd probably use a list comprehension:
#lang racket
(for*/sum ([i (in-range 1 5)]
[j (in-range (add1 i) 5)])
(* i j))
The core functionality you need for a simple implementation of the inclusion-exclusion principle is to generate all k-element subsets of the index set. Using lists, that is an easy recursion:
pick :: Int -> [a] -> [[a]]
pick 0 _ = [[]] -- There is exactly one 0-element subset of any set
pick _ [] = [] -- No way to pick any nonzero number of elements from an empty set
pick k (x:xs) = map (x:) (pick (k-1) xs) ++ pick k xs
-- There are two groups of k-element subsets of a set containing x,
-- those that contain x and those that do not
If pick is not a local function whose calls are 100% under your control, you should add a check that the Int parameter is never negative (you could use Word for that parameter, then that's built into the type).
If k is largish, checking against the length of the list to pick from prevents a lot of fruitless recursion, so it's better to build that in from the start:
pick :: Int -> [a] -> [[a]]
pick k xs = choose k (length xs) xs
choose :: Int -> Int -> [a] -> [[a]]
choose 0 _ _ = [[]]
choose k l xs
| l < k = [] -- we want to choose more than we have
| l == k = [xs] -- we want exactly as many as we have
| otherwise = case xs of
[] -> error "This ought to be impossible, l == length xs should hold"
(y:ys) -> map (y:) (choose (k-1) (l-1) ys) ++ choose k (l-1) ys
The inclusion-exclusion formula then becomes
inclusionExclusion indices
= sum . zipWith (*) (cycle [1,-1]) $
[sum (map count $ pick k indices) | k <- [1 .. length indices]]
where count list counts the number of elements of the intersection of [subset i | i <- list]. Of course, you need an efficient way to calculate that, or it would be more efficient to find the size of the union directly.
There's much room for optimisation, and there are different ways to do it, but that's a fairly short and direct translation of the principle.
Here is a possible way with Scheme. I've made the following function to create quantification
#lang racket
(define (quantification next test op e)
{lambda (A B f-terme)
(let loop ([i A] [resultat e])
(if [test i B]
resultat
(loop (next i) (op (f-terme i) resultat)) ))})
With this function you can create sum, product, generalized union and generalized intersection.
;; Arithmetic example
(define sumQ (quantification add1 > + 0))
(define productQ (quantification add1 > * 1))
;; Sets example with (require
(define (unionQ set-of-sets)
(let [(empty-set (set))
(list-of-sets (set->list set-of-sets))
]
((quantification cdr eq? set-union empty-set) list-of-sets
'()
car)))
(define (intersectionQ set-of-sets)
(let [(empty-set (set))
(list-of-sets (set->list set-of-sets))
]
((quantification cdr eq? set-intersect (car list-of-sets)) (cdr list-of-sets)
'()
car)))
This way you can do
(define setA2 (set 'a 'b))
(define setA5 (set 'a 'b 'c 'd 'e))
(define setC3 (set 'c 'd 'e))
(define setE3 (set 'e 'f 'g))
(unionQ (set setA2 setC3 setE3))
(intersectionQ (set setA5 setC3 setE3))
I work on something similar in Haskell
module Quantification where
quantifier next test op =
let loop e a b f = if (test a b)
then e
else loop (op (f a) e) (next a) b f
in loop
quantifier_on_integer_set = quantifier (+1) (>)
sumq = quantifier_on_integer_set (+) 0
prodq = quantifier_on_integer_set (*) 1
But I never go further... Probably that you can start from this however.

Resources