datatype 'a stream =
Nil
| Cons of 'a * (unit -> 'a stream);
exception Bad of string;
fun from seed next = Cons (seed, fn () => from (next seed) next);
fun head (Nil) = raise Bad "got nil in head"
| head (Cons (h, t)) = h;
fun tail (Nil) = raise Bad "got nil in tail"
| tail (Cons (h, t)) = t ();
fun take 0 stream = []
| take n (Nil) = raise Bad "got nil in take"
| take n (Cons (h, t)) = h :: (take (n - 1) (t ()));
I am try to write an infinite factorial stream, where it takes two stream and outputs one stream.
fun fac(a,b) = Cons(a, fn() => fac(b, a*(b-1));
This is what I have so far. But it does not give me the right answer.
I don't think it makes sense for a factorial stream to take any inputs, since factorials form a specific sequence.
Instead, you need a helper function that manages the internal state (n and n!), and then the stream itself is just a value:
local
(* returns a stream consisting of
nFac,
nFac * nextN,
nFac * nextN * (nextN + 1),
nFac * nextN * (nextN + 1) * (nextN + 2),
...
*)
fun facHelper (nFac, nextN) = Cons (nFac, fn () => facHelper (nFac * nextN, nextN + 1))
in
(* a stream consisting of 0!, 1!, 2!, 3!, ... *)
val factorials = facHelper (1, 1)
end
Alternatively, you can create a stream of the numbers 1, 2, 3, …, and a stream-reducer that, given a stream s, returns a stream of 1, s1, s1s2, s1s2s3, …:
local
(* returns a stream consisting of n, n + 1, n + 2, n + 3, ... *)
fun positiveIntegersHelper n = Cons (n, fn () => positiveIntegersHelper (n + 1))
in
(* a stream consisting of 1, 2, 3, 4, ... *)
val positiveIntegers = positiveIntegersHelper 1
end
(* Note: the above could also have been written using your 'from' function, as
val positiveIntegers = from 1 (fn n => n + 1)
*)
(* given a function f, an initial value seed, and a stream consisting of [s1, s2, s3, ...],
returns a stream consisting of
[seed, f(s1, seed), f(s2, f(s1, seed)), f(s3, f(s2, f(s1, seed))), ...]
-- so, somewhat analogous to List.foldl, except that it returns a stream of all partial
results, instead of just the final result.
*)
fun reduceStream _ seed Nil = Cons (seed, fn () => Nil)
| reduceStream f seed (Cons (h, tf)) =
Cons (seed, fn () => reduceStream f (f (h, seed)) (tf ()))
(* a stream consisting of 0!, 1!, 2!, 3!, ... *)
val factorials = reduceStream op* 1 positiveIntegers
Related
i have a list , and a tuple (start,end,interval)
i am trying to iterate over the list and return the elements that are in list from start to end with interval steps .
for example:
cutt [1,2,3,4,77,8,7] (1,5,2);
val it = [2,4,8] : int list;
the problem is that i can't use recursion ,
i was thinking to use foldl but the problem is how to skip over elements i don't want to use list.nth?
i would appriciate little hints ! thank you
It sounds like you need two functions. The first step is to retrieve a slice of your list between indices. This sounds suspiciously related to a solution posted very recently.
fun slice'(lst, start, stop) =
let
val (_, lst') = foldl
(fn (v, (idx, acc)) =>
if idx >= start andalso idx <= stop then
(idx + 1, v::acc)
else
(idx + 1, acc))
(0, [])
lst
in
List.rev(lst')
end;
If we try slice'([1,2,3,4,77,8,7], 1, 5) the result is [2, 3, 4, 77, 8].
To get to [2, 4, 8] we just need to drop every second element. This can be defined in terms of simple recursion as follows.
fun dropn(n, lst) =
let
fun dropn'(_, _, []) = []
| dropn'(n, c, x::xs) =
if c = n then x :: dropn'(n, 1, xs)
else dropn'(n, c + 1, xs)
in
dropn'(n, n, lst)
end
But apparently you can't use recursion, so let's use a fold.
fun drop(n, lst) =
List.foldl
(fn (x, (acc, i)) => if i = n then (x :: acc, 1) else (acc, i + 1))
([], n)
lst
Now if we try drop(2, [1,2,3,4,77,8,7]) we get ([7, 77, 3, 1], 1) which does contain the list we want, but also the counter, and the list is backwards because of the way we've built it up. Let's consider how that accumulator works as we step through this simple example.
Initial state:
lst: [1,2,3,4,77,8,7]
acc: []; i: 2
First iteration:
x: 1
acc: [1]; i: 2
Second Iteration:
x: 2
acc: 1 :: []; i: 1
Third iteration:
x: 3
acc: 3 :: 1 :: []; i: 2
Fourth iteration:
x: 4
acc: 3 :: 1 :: []; i: 1
Fifth iteration:
x: 77
acc: 77 :: 3 :: 1 :: []; i: 2
Sixth iteration:
x: 8
acc: 77 :: 3 :: 1 :: []; i: 1
Seventh iteration:
x: 7
acc: 7 :: 77 :: 3 :: 1 :: []; i: 2
Final step:
remaining list: []
acc: 7 :: 77 :: 3 :: 1 :: [] or [7, 77, 3, 1]; i: 1
Easy enough, though, to extract and reverse that list.
fun drop(n, lst) =
let
val (lst', _) = List.foldl
(fn (x, (acc, i)) => if i = n then (x :: acc, 1) else (acc, i + 1))
([], n)
lst
in
List.rev lst'
end
So now drop(2, [1,2,3,4,77,8,7]) evaluates to [1, 3, 77, 7].
Between these two answers, it should be very straightforward to put together a solution to your problem, and hopefully to see why it works.
One solution to correctly skip elements you don't want in your
resulting list, is to add a parameter to your function used to fold
your list. The meaning of this parameter is basically "how much items
you still want to skip".
As an example, below is a solution that uses List.foldl. The
function used to fold items of the list takes two parameters: the
first one is the one discussed above and the second one is the
resulting list being constructed.
fun cutt lst (idx_start, idx_end, interval) = let
val (_, result) =
List.foldl
(fn (x, (0, result)) =>
(* no more item to skip => add x to the resulting list *)
(interval - 1, x :: result)
| (_, (n, result)) =>
(* there are still items to skip *)
(n - 1, result))
(idx_start, []) (* initially we skip idx_start items *)
lst
in
(* items are prepended in the resulting list in reverse order =>
reverse the list *)
List.rev result
end;
val x = cutt [1, 2, 3, 4, 77, 8, 7] (1, 5, 2);
Of course the function needs to be adapted as it does not take care
of the idx_end parameter.
I want to search in with searchingElements list inside each second element in tuple list and count if there are months in the list inside tuple lists as it shown in the test, I don't know if it should done by recursion, which I have no clue how to use here.
fun number_in_months(months : (int * int * int) list, months2 : (int * int * int) list,
months3 : (int * int * int) list, searchingElements : int list) =
if #2 (hd (tl months)) = (hd searchingElements)
then
1
else
0
val test3 = number_in_months ([(2012, 2, 28), (2013, 12, 1), (2011, 3, 31), (2011, 4, 28)], [2, 3, 4]) = 3
I get these 2 errors that I understood later I can't compare between list and tuple list
(fn {1=1,...} => 1) (hd number)
main.sml:30.2-30.30 Error: operator and operand do not agree [overload - bad instantiation]
stdIn:2.1-2.5 Error: unbound variable or constructor: fun3
It's really misleading if we read the function code and the test as they both are not type consistent in the very first place.
If I follow the test function which is
val test3 = number_in_months ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[2,3,4]) = 3
then the type of number_in_months should be
val number_in_months = fn: ('a * ''b * 'c) list * ''b list -> int
which is a pair(2-tuple) and the function which is supposed to implement the logic
fun fun3 (months :(int*int*int) list, months2: (int*int*int) list, months3:
(int*int*int) list, searchingElements: int list)
is actually a function with a parameter which is a 4-tuple and a mismatch is evident. Also the parameters months2 and months3 are not used anywhere. Plus, each of the so called months parameters are of type list in themselves. Furthermore, except for the test3 line, there isn't anything which is quite meaningful to come-up with an answer or even a reply.
However, following the test3 line, I have attempted to write a function that at least gets the thing done and is as follows:
fun number_in_months (date_triples, months) =
let
fun is_second_of_any_triple ele = List.exists (fn (_, x, _) => x = ele)
in
List.foldl (fn (curr, acc) => if is_second_of_any_triple curr date_triples then acc + 1 else acc) 0 months
end
A version with explicit recursion:
Suppose we had a function that counted the occurrences of a single number in a list of tuples;
month_occurrences: ((int * int * int) list * int) -> int
Then we could recurse over the list of numbers, just adding as we go along:
fun number_in_months(dates, []) = 0
| number_in_months(dates, m::ms) = month_occurrences(dates, m) + number_in_months(dates, ms)
And month_occurrences with a straight recursion might look like
fun month_occurrences([], _) = 0
| month_occurrences((_, m, _)::ds, m') = (if m = m' then 1 else 0) + month_occurrences(ds, m')
How would I go about traversing a list in SMLNJ. I have been at this for 3 hours now and I cannot figure it out for the life of me.
So just to traverse and print a list out. In the simplest way [5,2,3] would print out 5 2 3 or a list variant of this.
How would I go about traversing a list in SMLNJ
It depends on the type of traversal you want to do: mapping, folding, iterating.
Using recursion:
(* mapping: *)
fun incr_each_by_1 [] = []
| incr_each_by_1 (x::xs) = x + 1 :: incr_each_by_1 xs
val demo_1 = incr_each_by_1 [5,2,3] (* [6,3,4] *)
(* folding: *)
fun sum_all_together [] = 0
| sum_all_together (x::xs) = x + sum_all_together xs
val demo_2 = sum [5,2,3] (* 10 *)
(* iteration: *)
fun print_each [] = ()
| print_each (x::xs) = ( print (Int.toString x ^ "\n") ; print_each xs )
val demo_3 = print_each [5,2,3] (* no result, but side-effect *)
Using higher-order functions:
val demo_1 = List.map (fn x => x + 1) [5,2,3]
val demo_2 = List.foldl (fn (x, result) => x + result) 0 [5,2,3]
val demo_3 = List.app (fn x => Int.toString x ^ "\n") [5,2,3]
I need to
Write a function separate of type int * 'a * 'a list -> 'a lst such that
separate (k, x, l) returns the list that inserts element x after each k elements of list l (counting from
the end of the list). For example, separate (1, 0, [1,2,3,4]) should return [1,0,2,0,3,0,4] and
separate (3, 0, [1,2,3,4]) should return [1,0,2,3,4].
So far, this is what I have, but it is causing an error. Can anyone help me?
fun separate (k: int, x: 'a, l: 'a list) : 'a list =
let val count:int = k
in foldr(
(fn (h, t) =>
if count = 0
then count := 1 in
x::h::t
else count = count + 1 : int
h::t
)
Actually the logic is quite right, but it should be implemented by passing changed state into another iteration of foldr due to immutability:
fun separate (k: int, x: 'a, l: 'a list) : 'a list =
#2 (foldr (fn (h, (count, t)) =>
if count = 0
then (k - 1, h::x::t)
else (count - 1, h::t)
) (k, []) l);
Thus, instead of initiating count as a variable, we initiate foldr with tuple (k, []) (where k is the initial value of count and [] is the resulting list) and then decrease the count every step of the iteration.
I'm having a problem grouping these code lines into one function
sumFirstEven : int * int seq -> int
such that sumFirstEven (5, s) is the sum of the first 5 even elements of the sequence s
I've been told that I need to group my lines into one function that includes "let-in commands"
these are my lines for these func:
datatype 'a seq=null|SEQ of 'a*(unit->'a seq);
fun head(SEQ(x,_))=x
|head null=raise Empty;
fun tail(SEQ(_,xf))=xf()
|tail null=raise Empty;
fun sumFirstEven(0,_)=0
|sumFirstEven(n,null)=0
|sumFirstEven(n,xs)=if(head(xs) mod 2=0)then head(xs)+sumFirstEven(n-1,tail(xs))
else sumFirstEven(n,tail(xs));
fun seqFrom i=SEQ(i,fn()=>seqFrom(i+1));
val seqStart=seqFrom 1;
sumFirstEven(5,seqStart);
My function works fine but I dont know how to regroup all of these lines
correctly
The beauty of pattern matching is that it often obviates helper functions like head and tail.
fun sumFirstEven (0, _) = 0
| sumFirstEven (_, null) = 0
| sumFirstEven (n, SEQ (h, t)) =
case h mod 2
of 0 => h + sumFirstEven (n-1, t ())
| _ => sumFirstEven (n, t ())
Since the first two clauses didn't match, there's no need in the third clause to call a function with a failure condition like head... we already know the data is in the right form!
The pattern matching in the function clause serves the same role that a let-in-end expression (not command!) would.
Given your lazy list type,
datatype 'a seq = Null | Seq of 'a * (unit -> 'a seq)
you might want the helper function,
fun even n = n mod 2 = 0
and you might want to either recurse manually,
fun sumFirstEven (0, _) = 0
| sumFirstEven (_, Null) = 0
| sumFirstEven (n, Seq (x, seqf) =
if even x
then x + sumFirstEven (n-1, seqf ())
else sumFirstEven (n, seqf ())
or you may want to accumulate the result in a function parameter,
fun sumFirstEven (n, seq) =
let fun sfe (0, _, result) = result
| sfe (_, Null, result) = result
| sfe (n, Seq (x, seqf), result) =
if even x
then sfe (n-1, seqf (), result + x)
else sfe (n, seqf (), result)
in sfe (n, seq, 0) end
to make it tail-recursive (i.e. use a fixed amount of stack frames). More conveniently, you might want to extract the recursion part of the function into a separate higher-order fold combinator,
fun foldseqn _ e 0 _ = e
| foldseqn _ e _ Null = e
| foldseqn f e n (Seq (x, seqf)) =
case f (x, e) of
(e', true) => foldseqn f e' (n-1) (seqf ())
| (e', false) => foldseqn f e' n (seqf ())
fun sumFirstEven (n, seq) =
foldseqn (fn (x, sum) => if even x
then (sum + x, true)
else (sum, false)) 0 n seq
And a quick test,
fun nats n = Seq (n, fn () => nats (n+1))
val twelve = sumFirstEven (3, nats 1) (* 2+4+6 *)
Edit: Responded to Nick's comment, thanks.