I don't understand how could I call lseq function so that it will run forever.
type 'a llist = LazyList of 'a * (unit -> 'a llist)
let rec lseq nr =
LazyList (nr, fun () -> lseq (nr+1))
if i call
lseq 5
I get
int llist = LazyList (5, <fun>)
Each call to lseq will construct a new value of type 'a llist. The value will consist of two parts. The first part is a list element, produced on this step, and the second one is a function that will produce the rest of the list. Then the function is not called yet, so the function doesn't cycle.
In layman terms, a list is a pair that has one value, and a phone number, where you should call to get the rest. So if you need more values, you need to call more, e.g.,
let rec print_lseq (LazyList (x,next)) =
print_int x;
print_lseq (next ())
Of course, this function will never terminate and will print an infinite sequence of numbers.
What concerning your example, lseq 5 is an infinite sequence that looks like: 5, 6, 7, .... It is not eagerly constructed in the memory, but instead it is more like a recipe, how to construct the sequence.
Related
here is my code:
val fibs =
let
val rec fibs_help =
fn(n, next) => Cons(n, (fn()=>fibs_help(next, n+next)) )
in
fibs_help(0, 1)
end;
val list = fibs(10)
And here is the error:
Error: unbound variable or constructor: Cons
The error message refers to a missing data type constructor, Cons. It is missing because you have no data type declaration in the mentioned code. You are probably missing a line that looks like:
datatype 'a seq = Cons of 'a * (unit -> 'a seq)
If you insert that declaration at the top of your code, you get a new error message:
! val list = fibs(10)
! ^^^^
! Type clash: expression of type
! int seq
! cannot have type
! 'a -> 'b
You get this error because you define fibs as a sequence of integers, but in the last line, you refer to fibs as a function that takes, presumably, a number of elements you wish to extract from that sequence. There is nothing wrong with the definition of the sequence. Here's how I would format the first part of the code:
val fibs =
let fun fibs_help (n, next) = Cons (n, fn () => fibs_help (next, n+next))
in fibs_help(0, 1)
end
In order to extract a concrete amount of elements from this infinite sequence into e.g. a finite list requires a little more work. Write a function take (i, s) that produces a list of the first i elements of the sequence s:
fun take (0, ...) = ...
| take (i, Cons (n, subseq_f)) = ...
The base case is when you want a list of zero elements from any sequence. Consider if/what you need to pattern match on the input sequence and what the result of this trivial case is. The recursive case is when you want a list of one or more elements from any sequence; do this by including the one element n in the result and solve a problem of the same structure but with a size one less using take, i and subseq_f.
Once this function works, you can use it to get your list of ten elements:
val ten_first = take (10, fibs)
I have to generate an infinite list containing a Fibonacci sequence. I am new to ML so I want to check if this is correct.
-datatype 'a infist=NIL
= | CONS of 'a * (unit -> 'a inflist);
- fun fib a b = CONS (a , fn()=> fib b (a+b));
val fib=fn: int->int-int inflist
Is this what is called a generator function?
Will it give me an actual output i.e the infinite fib sequence when I give a and b inputs?
Your datatype definition and your function definition seem correct. Although I still would have preferred a Fibonacci function that does not expect any arguments, to avoid the possibility of getting wrong input:
fun fibonacci () =
let
fun fib(a,b) = Cons(a+b, fn() => fib(b,a+b))
in
Cons(0, fn()=> fib(0,1))
end
This is what I would call a stream
When you invoke it, it'll give an element of type infislist. You may consider writing some other functions to process your stream and interpret its contents. You may want see some examples of this in my another answer, for example, functions like takeWhile, take, filter, zip and toList.
Here's what I've got so far...
fun positive l1 = positive(l1,[],[])
| positive (l1, p, n) =
if hd(l1) < 0
then positive(tl(l1), p, n # [hd(l1])
else if hd(l1) >= 0
then positive(tl(l1), p # [hd(l1)], n)
else if null (h1(l1))
then p
Yes, this is for my educational purposes. I'm taking an ML class in college and we had to write a program that would return the biggest integer in a list and I want to go above and beyond that to see if I can remove the positives from it as well.
Also, if possible, can anyone point me to a decent ML book or primer? Our class text doesn't explain things well at all.
You fail to mention that your code doesn't type.
Your first function clause just has the variable l1, which is used in the recursive. However here it is used as the first element of the triple, which is given as the argument. This doesn't really go hand in hand with the Hindley–Milner type system that SML uses. This is perhaps better seen by the following informal thoughts:
Lets start by assuming that l1 has the type 'a, and thus the function must take arguments of that type and return something unknown 'a -> .... However on the right hand side you create an argument (l1, [], []) which must have the type 'a * 'b list * 'c list. But since it is passed as an argument to the function, that must also mean that 'a is equal to 'a * 'b list * 'c list, which clearly is not the case.
Clearly this was not your original intent. It seems that your intent was to have a function that takes an list as argument, and then at the same time have a recursive helper function, which takes two extra accumulation arguments, namely a list of positive and negative numbers in the original list.
To do this, you at least need to give your helper function another name, such that its definition won't rebind the definition of the original function.
Then you have some options, as to which scope this helper function should be in. In general if it doesn't make any sense to be calling this helper function other than from the "main" function, then it should not be places in a scope outside the "main" function. This can be done using a let binding like this:
fun positive xs =
let
fun positive' ys p n = ...
in
positive' xs [] []
end
This way the helper function positives' can't be called outside of the positive function.
With this take care of there are some more issues with your original code.
Since you are only returning the list of positive integers, there is no need to keep track of the
negative ones.
You should be using pattern matching to decompose the list elements. This way you eliminate the
use of taking the head and tail of the list, and also the need to verify whether there actually is
a head and tail in the list.
fun foo [] = ... (* input list is empty *)
| foo (x::xs) = ... (* x is now the head, and xs is the tail *)
You should not use the append operator (#), whenever you can avoid it (which you always can).
The problem is that it has a terrible running time when you have a huge list on the left hand
side and a small list on the right hand side (which is often the case for the right hand side, as
it is mostly used to append a single element). Thus it should in general be considered bad
practice to use it.
However there exists a very simple solution to this, which is to always concatenate the element
in front of the list (constructing the list in reverse order), and then just reversing the list
when returning it as the last thing (making it in expected order):
fun foo [] acc = rev acc
| foo (x::xs) acc = foo xs (x::acc)
Given these small notes, we end up with a function that looks something like this
fun positive xs =
let
fun positive' [] p = rev p
| positive' (y::ys) p =
if y < 0 then
positive' ys p
else
positive' ys (y :: p)
in
positive' xs []
end
Have you learned about List.filter? It might be appropriate here - it takes a function (which is a predicate) of type 'a -> bool and a list of type 'a list, and returns a list consisting of only the elements for which the predicate evaluates to true. For example:
List.filter (fn x => Real.>= (x, 0.0)) [1.0, 4.5, ~3.4, 42.0, ~9.0]
Your existing code won't work because you're comparing to integers using the intversion of <. The code hd(l1) < 0 will work over a list of int, not a list of real. Numeric literals are not automatically coerced by Standard ML. One must explicitly write 0.0, and use Real.< (hd(l1), 0.0) for your test.
If you don't want to use filter from the standard library, you could consider how one might implement filter yourself. Here's one way:
fun filter f [] = []
| filter f (h::t) =
if f h
then h :: filter f t
else filter f t
I'm confused as to what the Cons() function does, in the function definition for from.
What Stream represents is a lazy and potentially infinite list. Since SML is eager, this needs to be done in a slightly roundabout way.
Let's first look at how ordinary lists work:
datatype 'a list = [] | :: of 'a * 'a list
The cons consists of two parts:
The first element in the list
The rest of the list
In the lazy list, it's pretty similar.
datatype 'a Stream = Nil | Cons of 'a * (unit -> 'a Stream)
Here the cons consists of the following:
The first element in the list
A function that produces the rest of the list when evaluated on ()
So, you can see that the principle is much the same, albeit a tad more difficult to work with.
Let's look at an example list:
fun succ n = Cons (n, fn () => succ (n+1))
val naturals = succ 0
What does this produce? Let's examine it.
naturals was defined to be succ 0, which in turn is defined to be Cons(0, fn () => succ 1). From this we can see that the first element in the list is 0.
Now let us go one step further. We evaluate fn () => succ 1, the second part of our Cons, on (), which produces succ 1, which in turn is Cons(1, fn () => succ 2). Now we can see that the second element in the list is 1.
If we repeat this process, we get that the list represents the infinite list [0, 1, 2, ...].
You can also see this by trying to do
val firstnats = take 10 naturals;
and seeing what you get.
It's one of Stream's two constructors. See the second line of that screenshot -- that's all there is to Cons.
I need a function that recursively returns (not prints) all values in a list with each iteration. However, every time I try programming this my function returns a list instead.
let rec elements list = match list with
| [] -> []
| h::t -> h; elements t;;
I need to use each element each time it is returned in another function that I wrote, so I need these elements one at a time, but I can't figure this part out. Any help would be appreciated.
Your function is equivalent to :
let rec elements list =
match list with
| [] -> []
| h :: t -> elements t
This happens because a ; b evaluates a (and discards the result) and then evaluates and returns b. Obviously, this is in turn equivalent to:
let elements (list : 'a list) = []
This is not a very useful function.
Before you try solving this, however, please understand that Objective Caml functions can only return one value. Returning more than one value is impossible.
There are ways to work around this limitation. One solution is to pack all the values you wish to return into a single value: a tuple or a list, usually. So, if you need to return an arbitrary number of elements, you would pack them together into a list and have the calling code process that list:
let my_function () = [ 1 ; 2; 3; 4 ] in (* Return four values *)
List.iter print_int (my_function ()) (* Print four values *)
Another less frequent solution is to provide a function and call it on every result:
let my_function action =
action 1 ;
action 2 ;
action 3 ;
action 4
in
my_function print_int
This is less flexible, but arguably faster, than returning a list : lists can be filtered, sorted, stored...
Your question is kind of confusing - you want a function that returns all the values in a list. Well the easiest way of returning a variable number of values is using a list! Are you perhaps trying to emulate Python generators? OCaml doesn't have anything similar to yield, but instead usually accomplishes the same by "passing" a function to the value (using iter, fold or map).
What you have currently written is equivalent to this in Python:
def elements(list):
if(len(list) == 0):
return []
else:
list[0]
return elements(list[1:])
If you are trying to do this:
def elements(list):
if(len(list) > 0):
yield list[0]
# this part is pretty silly but elements returns a generator
for e in elements(list[1:]):
yield e
for x in elements([1,2,3,4,5]):
dosomething(x)
The equivalent in OCaml would be like this:
List.iter dosomething [1;2;3;4;5]
If you are trying to determine if list a is a subset of list b (as I've gathered from your comments), then you can take advantage of List.mem and List.for_all:
List.for_all (fun x -> List.mem x b) a
fun x -> List.mem x b defines a function that returns true if the value x is equal to any element in (is a member of) b. List.for_all takes a function that returns a bool (in our case, the membership function we just defined) and a list. It applies that function to each element in the list. If that function returns true for every value in the list, then for_all returns true.
So what we have done is: for all elements in a, check if they are a member of b. If you are interested in how to write these functions yourself, then I suggest reading the source of list.ml, which (assuming *nix) is probably located in /usr/local/lib/ocaml or /usr/lib/ocaml.