Printing int -> int list in ocaml - list

The function 'succ_di_nodo' prints the successors of a given node in a given graph:
type peso = int;;
type 'a grafo = Gr of (int * peso * int) list;;
let g1 = Gr [(1,3,2);(1,9,5);(2,2,3);(5,4,6);(3,1,6);(3,7,4);(6,2,7);(4,4,6)];;
let rec succ_di_nodo (Gr grafo) nodo =
let rec f_ausiliaria = function
[] -> []
| (x,y,z)::coda ->
if x = nodo then z::f_ausiliaria coda
else if z = nodo then x::f_ausiliaria coda
else f_ausiliaria coda in f_ausiliaria grafo;;
g1 is the Graph itself and the value are (node1,weight,node2).
When i pass to the function succ_di_nodo the value for example (succ_di_nodo g1 4) it returns correctly: int list = [3;6].
The question is, when i call the function (succ_di_nodo g1) without giving a specific node it return the type int -> int list; so it is not an empty list and i want to see the exact return value of this function call. How can i print the type int -> int list in Ocaml?

When you call succ_di_nodo with only one argument it returns a function that accepts the second argument and returns the list of successors. This is called partial application.
The int -> int list type denotes a function that takes one argument of type int and returns a value of type int list. You can't print a function value (the default printer will just print <fun>). In order to print a function, you would need to enumerate all values in the input domain, which is usually infinite (or close to that). For testing purposes, you can, of course, apply you function to a set of input values, to see what it outputs, e.g.,
List.init 10 (succ_di_nodo g1);;
will apply (succ_di_nodo g1) to 0, 1, and so on up to 9 and return the result in a list, i.e., the output will be
[[]; [2; 5]; [1; 3]; [2; 6; 4]; [3; 6]; [1; 6]; [5; 3; 7; 4]; [6]; []; []]
You can also trace your function in a toplevel (i.e., when you are running your function in the interpreter), by using the #trace directive. It will show the arguments that go into the function and values that go out. For the sake of experiment try this in the toplevel:
#trace succ_di_nodo;;
(you need to type the leading # it is a part of the directive name). When you will apply succ_di_nodo to two arguments, you will notice that the function first returns a new function, codenamed succ_di_nodo*, which is the result of the application of the first argument, and, finally, the second argument is passed to the returned succ_di_nodo* function. This process is called currying, which is an essential concept in functional programming.
# #trace succ_di_nodo;;
succ_di_nodo is now traced.
# succ_di_nodo g1 0;;
succ_di_nodo <--
Gr
[(1, 3, 2); (1, 9, 5); (2, 2, 3); (5, 4, 6); (3, 1, 6); (3, 7, 4);
(6, 2, 7); (4, 4, 6)]
succ_di_nodo --> <fun>
succ_di_nodo* <-- 0
succ_di_nodo* --> []
- : int list = []
#
When you are done, you can untrace a function with the #untrace directive.

Related

How to compare and search for an element in a list with a tuple inside a list SML

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')

SML: define an array

Forgive me, if it's trivial but
I am reading the documentation of arrays in SML and I am confused . I see many functions but how do I make my own array; How do I initialize one? (Everything , I tried failed)
For example a list is initialised like that :
val l = [1,2,3];
if I wanted [1,2,3] to be an array 1x3 ?
I found how to initialize one array but with only one value like:
array(4,0) (*creates [0,0,0,0] *)
but what about the [1,2,3];
You have (at least) two possibilities for that, either using
Array.fromList:
val a = Array.fromList [1, 2, 3];
either using Array.tabulate:
fun incr x = x + 1;
val a = Array.tabulate (3, incr);
Array.tabulate takes two arguments: the size of your array and a
function used to initialise the items of your array.
val a = Array.tabulate (3, incr);
is thus equivalent to:
val a = Array.fromList [incr(0), incr(1), incr(2)];
Note that I have defined a function incr but I could also have done:
val a = Array.tabulate (3, fn x => x + 1);

SML List [1, 2, 3,...n]

I need to create a list [1,2,3...n] without using pre implemented List fuctions. I can make the list backwards by writing :
fun makeList(x : int) =
if x = 0
then []
else x :: makeList(x-1)
Then I could reverse it and get [1,2,3,4] if inputting 4. How would I do this in only one function?
You've made the reverse list in one function and without using the List library.
To make it in the right order, you can use an accumulating argument:
fun makeList 0 result = result
| makeList n result = makeList (n-1) (n :: result)
Testing this:
- makeList 10 [];
> val it = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] : int list
This function takes an extra argument in which it accumulates the result in the right order.
This is what trips up other correspondents in this Q&A and what has made previous answerers delete their responses: Either you accept that this makeList takes an extra empty list as initial argument, which is kind of messy, or you nest this function inside another function that hides this mechanism:
fun makeList n =
let fun go 0 result = result
| go i result = go (i-1) (i :: result)
in go n [] end
But then you would not have used one function. Unless you mean one exposed function, since the inner function is only available in the context of the definition of makeList. As the problem statement is unclear about this, answering can be unsatisfactory.
Either you make one function, and allow for its type signature to be different (taking an extra argument), or you make one exposed function and allow for it to have an inner function that accumulates the result in reverse.

How can i make inner recursive function reach original variable in OCaml?

I am learning OCaml and now stuck with a code.
This is a code that makes a list of the accessible nodes from a graph.
type graph = (vertex * vertex) list
and vertex = int
let rec sort lst =
match lst with
[] -> []
| h::t -> insert h (sort t)
and insert n lst =
match lst with
[] -> [n]
| h::t -> if n <= h then n :: lst else h :: insert n t;;
let rec remove lst =
match lst with
| [] -> []
| x::[] -> x::[]
| x::y::tl ->
if x=y then remove (y::tl)
else x::remove (y::tl);;
let rec reach : graph * vertex -> vertex list
= fun (g, v) ->
match g with
|[] -> []
|h::t ->let x = [] in
match h with
|a,b -> if a = v then remove(sort(v::x) # (reach (g, b)))
else
remove(sort(v::reach (t, v)));;
reach([(1,2);(2,3);(3,4);(4,2);(2,5)],4);;
I think my code is meaninglessly complicated due to my lack of coding ability.
Besides, the main problem that I confront now is that I cannot make the recursive function 'reach' to access with original list 'g' as it goes recursive in else condition as it access with list 't'.
trace says
reach <-- ([(1, 2); (2, 3); (3, 4); (4, 2); (2, 5)], 4)
reach <-- ([(2, 3); (3, 4); (4, 2); (2, 5)], 4)
reach <-- ([(3, 4); (4, 2); (2, 5)], 4)
reach <-- ([(4, 2); (2, 5)], 4)
reach <-- ([(4, 2); (2, 5)], 2)
reach <-- ([(2, 5)], 2)
reach <-- ([(2, 5)], 5)
reach <-- ([], 5)
reach --> []
reach --> [5]
reach --> [2; 5]
reach --> [2; 5]
reach --> [4; 2; 5]
reach --> [2; 4; 5]
reach --> [2; 4; 5]
reach --> [2; 4; 5]
- : vertex list = [2; 4; 5]
First, I claimed a new variable with let y = g and change code
|a,b -> if a = v then remove(sort(v::x) # (reach (y, b)))
else
remove(sort(v::reach (t, v)));;
as I believed that the duplicates will be removed by fun 'remove' and inner function will access with list y, not t which lost its head. However, things did
not go as I planned. It still gives me a same result.
To make function access with original list 'g' in else condition what should I do...?
reach <-- ([(1, 2); (2, 3); (3, 4); (4, 2); (2, 5)], 4)
reach <-- ([(2, 3); (3, 4); (4, 2); (2, 5)], 4)
reach <-- ([(3, 4); (4, 2); (2, 5)], 4)
reach <-- ([(4, 2); (2, 5)], 4)
reach <-- ([(1, 2); (2, 3); (3, 4); (4, 2); (2, 5)], 2)
(*I want function goes back to original list as the variable changes like above*)
You can define an auxiliary function:
let reach g v =
let rec aux g' v' = ... (* here you can use g as the auxiliary function defines g' instead *)
in aux g v
Note that I also define the function with two arguments instead of one tuple, it's more idiomatic :)
Also if v' is always the same value the auxiliary function need not redefine it
let reach g v =
let rec aux g' = ...
in aux g v
One more remark. You can du deeper pattern matching, e.g.:
match g with
|[] -> []
|(a,b)::t -> let x = [] in
if a = v
then remove(sort(v::x) # (reach (g, b)))
else remove(sort(v::reach (t, v)));;
No need for a second match.
Finally, you might be aware of the function keyword that creates a function of one argument creating pattern matching:
let f x = match x with
(* same as *)
let f = function
Therefore:
let reach (g:graph) (v:vertex) =
let aux v' = function (*we don't create a g' variable here, we match it straight *)
| [] -> []
| (a,b)::t as g' -> (* you can still define the variable in the matching if you need it *)
let x = [] in
if a = v
then remove(sort(v::x) # (aux b g')) (* or g if that's what you need *)
else remove(sort(v::aux v t))
in aux v g
would do the same as your code
Edit: correctected recusrive calls to reach by recursive calls to aux as it wouldn't work.
Answering directly to your question, here is how to access the original value in a recursive function
let to_matrix outer =
let rec loop = function
| [] -> []
| x :: xs -> [x::outer] # loop xs in
loop outer
This function will iterate over each element of a list and create a list of list, where each element is a list made of the original element prepended to the whole original list, e.g.,
# to_matrix [1;2;3];;
- : int list list =
[[1; 1; 2; 3]; [2; 1; 2; 3]; [3; 1; 2; 3]]
The example might be silly, but I hope it clarifies the technique. Here the idea is that we create an inner function, named loop in our case, which has its own parameter, and we recurse only on this parameter while leaving the original outer list intact.
While it is an idiomatic approach, in general it is not required to create an inner function or an auxiliary function. What is really needed, is an extra parameter, so that at the end of the day we will have two parameters - one which decreases with each iteration and the other which stays invariant, e.g.,
let rec to_matrix outer inner = match inner with
| [] -> []
| x :: xs -> [x::outer] # to_matrix outer xs
the only caveat of this approach is that now we have to pass the list twice, e.g.,
to_matrix [1;2;3] [1;2;3];;
That's why it is idiomatic to hide this function by a nicer interface.

How to generate an infinite list of fibonacci numbers using curried function in SMLNJ?

I have coded up a general purpose routine that takes multiple arguments and generates an infinite list of fibonacci numbers which is as follows:
datatype 'a seq = Nil | Cons of 'a * (unit -> 'a seq) ;
fun fibo (a,b) = Cons(a, fn () => fibo(b,a+b));
val fib = fibo(0 , 1);
But the problem is I want to use currying technique to generate this infinite list of fibonacci numbers starting from 0 and 1, I am totally perplexed about the concept of currying.
Can some enlighten me about the concept of currying by using this example? How do I use currying to generate an infinite list of fibonacci numbers in SMLNJ?
Here you go:
datatype 'a seq = Nil | Cons of 'a * (unit -> 'a seq) ;
fun fibo a b = Cons(a, fn () => fibo b (a + b));
val fib = fibo 0 1;
And another (very useful) curried function:
(* take n seq returns the first n items in seq. Raises Subscript if there
are too few items. *)
fun take 0 _ = []
| take _ Nil = raise Subscript
| take n (Cons (a,f)) = a :: take (n - 1) (f ())
Example (in the mosml interpreter, so it might look slightly different from SML/NJ):
- take 10 fib;
> val it = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] : int list
And just to show off a little of the power of currying:
val firstTen = take 10
- firstTen fib;
> val it = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] : int list
What happens here, is that I only give take one argument. take has type int -> 'a seq -> 'a list, so by giving it the int argument, I get something of type 'a seq -> 'a list - namely, a function that returns 10 items of the 'a seq you give it as input.
Your definition is a little wrong as it mixes curried and uncurried forms of fibo.
If I understand correctly, there's not much to enlighten you about at the level of coding. There's a tiny syntactic difference between the curried and uncurried definitions.
- fun plus_uncurried (a, b) = a + b;
val plus_uncurried = fn : int * int -> int
- plus_uncurried (3,5);
val it = 8 : int
- fun plus_curried a b = a + b;
val plus_curried = fn : int -> int -> int
- plus_curried 3 5;
val it = 8 : int
- val incr = plus_curried 1;
val incr = fn : int -> int
- incr 4;
val it = 5 : int
At the conceptual level, curried functions seem a little trickier, at least at first. I personally just think of a curried function as one that returns a function that wants more arguments. When you finally give the last argument you get your answer.
(I'm not sure why you tagged this question with OCaml, but in OCaml currying is the idiomatic form for functions. So you get used to it right away.)
It may be you're looking for something more complicated than a function of type int -> int -> int seq. If so, you'll need to describe a little more carefully what you're looking for. Just specifying the type of what you're looking for would probably help a lot.
Update
There's nothing more complicated in fibo than in the examples above, other than that you have a recursive call. If you just change the first part of fibo in the same way that plus_uncurried changes into plus_curried, you will have handled the definition part. To handle the calling part, change your recursive call in the same way that calls to plus_uncurried are changed into calls to plus_curried.