How does let work in this function? - recursion

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

Related

How do you generate all permutations of a list with repetition in a functional programming language?

I'm trying to self-learn some programming in a functional programming language and recently stumbled on the problem of generating all the permutations of length m from a list of length n, with repetition. Mathematically, this should result in a total of n^m possible permutations, because each of the m 'slots' can be filled with any of the n elements. The code I have currently, however, does not give me all the elements:
let rec permuts n list =
match n, list with
0, _ -> [[]]
| _, [] -> []
| n, h :: t -> (List.map (fun tt -> h::tt) (permuts (n-1) list))
# permuts n t;;
The algorithm basically takes one element out of a list with m elements, slaps it onto the front of all the combinations with the rest of the elements, and concatenates the results into one list, giving only n C m results.
For example, the output for permuts 2 [1;2;3] yields
[[1;1]; [1;2]; [1;3]; [2;2]; [2;3]; [3;3]]
whereas I actually want
[[1;1]; [1;2]; [1;3]; [2;1]; [2;2]; [2;3]; [3;1]; [3;2]; [3;3]]
-- a total of 9 elements. How do I fix my code so that I get the result I need? Any guidance is appreciated.
Your error appears on the second line of:
| n, h :: t -> List.map (fun tt -> h::tt) (permuts (n-1) list)
# permuts n t
Indeed, with this you are decomposing the set of n-tuples with k elements as the sum of
the set of (n-1)-tuples prefixed with the first element
the set of n-tuples with (k-1) elements
Looking at the cardinal of the three sets, there is an obvious mismatch since
k^n ≠ k^(n-1) + (k-1)^n
And the problem is that the second term doesn't fit.
To avoid this issue, it is probably better to write a couple of helper function.
I would suggest to write the following three helper functions:
val distribute: 'a list -> 'a list -> 'a list list
(** distribute [x_1;...;x_n] y returns [x_1::y;...x_n::y] *)
val distribute_on_all: 'a list -> 'a list list
(** distribute_on_all x [l_1;...;l_n] returns distribute x l_1 # ... # distribute x l_n *)
val repeat: int -> ('a -> 'a) -> 'a -> 'a
(** repeat n f x is f(...(f x)...) with f applied n times *)
then your function will be simply
let power n l = repeat n (distribute_on_all l) [[]]
In Haskell, it's very natural to do this using a list comprehension:
samples :: Int -> [a] -> [[a]]
samples 0 _ = [[]]
samples n xs =
[ p : ps
| p <- xs
, ps <- samples (n - 1) xs
]
It seems to me you never want to recurse on the tail of the list, since all your selections are from the whole list.
The Haskell code of #dfeuer looks right. Note that it never deconstructs the list xs. It just recurses on n.
You should be able to copy the Haskell code using List.map in place of the first two lines of the list comprehension, and a recursive call with (n - 1) in place of the next line.
Here's how I would write it in OCaml:
let perm src =
let rec extend remaining_count tails =
match remaining_count with
| 0 -> tails
| _ ->
(* Put an element 'src_elt' taken from all the possible elements 'src'
in front of each possible tail 'tail' taken from 'tails',
resulting in 'new_tails'. The elements of 'new_tails' are one
item longer than the elements of 'tails'. *)
let new_tails =
List.fold_left (fun new_tails src_elt ->
List.fold_left (fun new_tails tail ->
(src_elt :: tail) :: new_tails
) new_tails tails
) [] src
in
extend (remaining_count - 1) new_tails
in
extend (List.length src) [[]]
The List.fold_left calls may look a bit intimidating but they work well. So it's a good idea to practice using List.fold_left. Similarly, Hashtbl.fold is also common and idiomatic, and you'd use it to collect the keys and values of a hash table.

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)

Tail recursion in OCaml

I'm trying to implement merge function in OCaml using Tail recursion but I face awkward results. Could anyone help me out with this. Thanks in advance.
let rec merge_helper l1 l2 accum =
match l1 with
[] -> l2#accum
| hd::tl -> (match l2 with
[] -> l1#accum
|x::xs -> merge_helper tl xs l1#l2#accum);;
let merge l1 l2 = merge_helper l1 l2 [];;
merge [1;2;4] [3;4;5];;
- : int list = [4; 5; 2; 4; 4; 5; 1; 2; 4; 3; 4; 5]
First of all your implementation doesn't run in a constant stack space. The xs # ys operation is not tail-recursive, and will make List.length xs calls (thus using this amount of stack frames). Also, the merge function usually preserves the ordering. So you need to have a comparison function, that will compare elements of the list. It is not absolutely clear, what you're expecting from you merge function, and why you classify your result as weird. For me the result matches with the code. What looks very strange to me is that although you're deconstructing l1 and l2 you're not using the result of the deconstruction and adds the whole lists l1 and l2 to the accumulator.
The approach should be the following, take an element from the first list, add this element to the accumulator, and switch the lists. So the induction step of the algorithm is the following:
let rec loop acc xs ys = match xs with
...
| x::xs -> loop (x::acc) ys xs
But if you want to merge two sorted lists preserving the order, then you need to take the smallest element of the two lists at each step.
let merge cmp xs ys =
let rec loop xs ys zs = match xs,ys with
| [],ss|ss,[] -> List.rev_append zs ss
| x :: txs, y :: tys ->
if cmp x y <= 0
then loop txs ys (x::zs)
else loop xs tys (y::zs) in
loop xs ys []
Here in the induction step, we take the smaller element, and continue with the two lists: the tail of the owner of the smaller element (because it is moved into the accumulator), and the second list is taken fully (because nothing is accumulated from it). Since we're prepending elements, they will be in a reversed order, so we will need to something to reverse the result (a usual trade off for tail-recursion). The base case, allows us to short-circuit our algorithm, when one or another list is shorter, and we don't need any more to compare them one-by-one, and can just append the rest part of the longer list to the accumulator zs. We use List.rev_append to append the leftover tail of the list to our accumulator. This function will prepend the reversed version of the first list to the second.

Finding largest value using tail recursion

I'm trying to find the largest value of a list using tail recursion. I can't use any auxiliary functions, though...so it must be done using recursion. I've written a function to find the max, starting from the head, but don't know how to implement it starting from the tail!
lmax [] = error "empty list"
lmax [x] = x
lmax (x::y::xs) =
if x > y then lmax (x::xs)
else lmax (y::xs)
The term "tail recursion" has nothing to do with the tail of a list, it is about the position of a function call.
You could say that a function call is in tail position, or that it is a tail call, if it's the last thing to happen in a function, i.e. no other computations depend on it.
Compare
fun foo xs = List.length xs
and
fun bar xs = 1 + List.length xs
In the first, the call to List.length is in tail position, because its result is returned immediately.
In the second, since we add 1 to the length, the call isn't a tail call.
"Tail recursion" is when a recursive function call is a tail call.
So you're in luck: your function already is tail recursive, since both conditional branches just return the value of a recursive call.
fun lmax l = let
fun lmaxh [] a = a
| lmaxh (x::xs) a = lmax xs Int.max(x,a)
in
lmaxh l 0
end
This works, assuming that the values are nonnegative integers.
Implementing tail recursion optimizes efficiency, because one doesn't have to evaluate and "pop-off" the stack after creating the recursive calls.
In general, to use tail-recursion, you must store some "memory" from prior computations to compare with in the current one, and update it for future computations, so as to immediately exit the function in the base case.
As such, your function is already tail recursive.
However, here is a tail-recursive maxList function, more in the spirit of SML :
fun maxList l =
let
fun maxListHelper l acc =
case l of
[] => acc
| x :: xs' => if x > acc
then (maxListHelper xs' x)
else (maxListHelper xs' acc)
in
case l of
[] => error "Empty List!"
| x :: xs' => maxListHelper xs' x
end
Your function is written in a very Haskell-like syntax with different cases handled on different lines without being explicitly declared as nested cases inside a function definition. This is quite alright, but is usually not done in SML.

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