Ocaml Print List of Tuples - ocaml

I would like to print a list of tuples of type (int * 'a) list. For example for printing this list of tuples
[(3, "toto");(1, "a")]
or this list
[(3, 4);(1, 7)]
How can I do that?

There is no built-in support for printing lists, tuples, or a type of any kind more generally. You have to be specific, and since a list can contain any type and a tuple can be a product of any types you have deconstruct it yourself and format it appropriately.
Here's an example of a function which iterates through the list, deconstructs each tuple, and formats them with a comma separating the items of the tuple and a semicolon separating the tuples themselves:
let rec print_tuples =
function
| [] -> ()
| (a, b) :: rest ->
Printf.printf "%i, %s; " a b;
print_tuples rest
let () =
print_tuples [(3, "toto");(1, "a")]
The documentation for Printf lists which other types you can print in this way, and the placeholders to use.

With Fmt (which is an improved api over Format) printing a list of tuple can be done by first defining a printer for a pair of int and string separated by a comma:
let pair_printer = Fmt.(pair ~sep:comma int string)
For the next step, we can define a printer for a list of those int * string tuples, separated by a semi-colon:
let list_printer = Fmt.(list ~sep:(const pf ";# ") pair_printer)
And then finally, we can use this printer with:
Fmt.pr "[%a]#." list_printer [1, "one"; 2, "two" ]

Related

f# iterate and use List<List<string>>

I have simple list that contains inside list
let ftss = [
["a","aData"],["b","bData"]
]
I want to iterate and access the elements "a" and "aData" etc.
I tried
List.iter (fun item ->
for i in 0..1 do
printfn "%s" item[i])
how do i access the elements inside the internal list?
Thanks
So, 1st thing is a comma isnt a delimter in a list, but in a tuple ',' so
let ftss = [
["a","aData"],["b","bData"]
]
is actually of type
val ftss: ((string * string) list * (string * string) list) list =
i.e. its a list of 1 entry of a tuple of a list of 1 entry each of a tuple.
which I THINK isnt what you intended?
I THINK you want (a ';' or new line delimits each entry)
let ftss3 = [
["a";"aData"]
["b";"bData"]
]
which is
val ftss3: string list list = [["a"; "aData"]; ["b"; "bData"]]
i.e. a list of a list of strings.
(I'd try to use FSI to enter these things in, and see what the types are)
so to iterate this list of lists you would go
List.iter (fun xs ->
List.iter (fun x ->
printfn "%s" x)
xs)
ftss3
As pointed out in the existing answer, you probably want to represent your data as a list of lists, for which you need to use the ; delimiter (to make a list) rather than , to construct a singleton containing a tuple.
I would just add that if you want to perform an imperative action with each of the items, such as printing, then it is perfectly reasonable to use an ordinary for loop:
let ftss = [
["a"; "aData"]; ["b"; "bData"]
]
for nested in ftss do
for item in nested do
printfn "%s" item

SMLNJ function that returns as a pair a string at the beginning of a list

So im really confused as i am new to sml and I am having trouble with syntax of how i want to create my function.
the instructions are as follows...
numberPrefix: char list → string * char list
Write a function named numberPrefix that returns (as a pair) a string representing the digit characters at the
beginning of the input list and the remaining characters after this prefix. You may use the Char.isDigit and
String.implode functions in your implementation.
For example,
numberPrefix [#"a", #"2", #"c", #" ", #"a"];
val it = ("", [#"a", #"2", #"c", #" ", #"a") : string * char list
numberPrefix [#"2", #"3", #" ", #"a"];
val it = ("23", [#" ", #"a"]) : string * char list
Here is my code so far...
fun numberPrefix(c:char list):string*char list =
case c of
[] => []
|(first::rest) => if isDigit first
then first::numberPrefix(rest)
else
;
I guess what i am trying to do is append first to a seperate list if it is indeed a digit, once i reach a member of the char list then i would like to return that list using String.implode, but I am banging my head on the idea of passing in a helper function or even just using the "let" expression. How can I essentially create a seperate list while also keeping track of where i am in the original list so that I can return the result in the proper format ?
First of all, the function should produce a pair, not a list.
The base case should be ("", []), not [], and you can't pass the recursive result around "untouched".
(You can pretty much tell this from the types alone. Pay attention to types; they want to help you.)
If you bind the result of recursing in a let, you can access its parts separately and rearrange them.
A directly recursive take might look like this:
fun numberPrefix [] = ("", [])
| numberPrefix (cs as (x::xs)) =
if Char.isDigit x
then let val (number, rest) = numberPrefix xs
in
((str x) ^ number, rest)
end
else ("", cs);
However, splitting a list in two based on a predicate – let's call it "splitOn", with the type ('a -> bool) -> 'a list -> 'a list * 'a list – is a reasonably useful operation, and if you had that function you would only need something like this:
fun numberPrefix xs = let val (nums, notnums) = splitOn Char.isDigit xs
in
(String.implode nums, notnums)
end;
(Splitting left as an exercise. I suspect that you have already implemented this splitting function, or its close relatives "takeWhile" and "dropWhile".)

Extract duplicates from nested list in SML

I have a function in SML that returns a nested list:
[["A", "B", "C"], ["A", "B"], ["B", "C"]]]
Is it possible to extract the elements that appear in these lists? i.e. output "B"?
I've tried something to the effect of List.filter (fn y=>(fn x=> x=y)) lst but to no avail..
Any hints?
I'll assume that the example nested list you give is representative, i.e., that elements are unique and ordered. I'll additionally leave out any explicit types or parameterized comparison functions, so the functions will operate on integers, not strings.
First, break down the problem down into comparing lists pairwise. Define a helper function common to find the common elements of a pair of ordered lists. It could look like this:
fun common(xs, []) = []
| common([], ys) = []
| common(x::xs, y::ys) = if x=y then x::common(xs, ys)
else if x < y then common(xs, y::ys)
else common(x::xs, ys)
It has type int list * int list -> int list.
To make this work for the nested list, you can base a solution on common, along the lines of:
fun nested_common([]) = []
| nested_common(x::[]) = x
| nested_common(x::y::rest) = nested_common(common(x,y)::rest)
This has type int list list -> int list.
Putting it to use (in Moscow ML):
- nested_common [[1,2,3], [1,2], [2,3]];
> val it = [2] : int list

Pattern Matching and List Comprehension in List of Tuples

type a = [(Int,Int,Int,Int)]
fun:: a -> Int
func [a,b,c,d] = ?
I have a list of tuples like this what i required is to apply list comprehensions or pattern matching .. example taking sum or filter only divide 2 numbers ... i just want a start how to access values and or a list comprehension to this List of Tuples
To sum up the as, use something like this:
type A = [(Int, Int, Int, Int)]
func :: A -> Int
func tuples = sum [a | (a, b, c, d) <- tuples]
Also note that a type alias must begin with an upper case letter. Lower case letters are used for type variables.
hammar's answer covered list comprehensions, the basic schema for recursive functions using pattern matching is:
f [] = ..
f ((a,b,c,d):xs) = ..
So you need to specify a base case for a list containing no 4-tuples, and a recursive case for when the list consists of a 4-tuple (a,b,c,d) followed by a (possibly empty, possibly non-empty) list of 4-tuples xs. The pattern on the second line is a nested pattern: it first matches the list against a pattern like (x:xs), i.e. element x followed by rest of list xs; and then it matches x against the 4-tuple structure.
Below, I'll give some basic examples. Note that you can also write this with standard higher-order functions, such as filter and map, and I'm deliberaty not mentioning things like #-patterns and strictness. I do not recommend doing it like this, but it's just to give you an idea!
When you want to sum the first part of the tuples, you could do it like this:
sum4 :: [(Int,Int,Int,Int)] -> Int
sum4 [] = 0
sum4 ((a,b,c,d):xs) = a + sum4 xs
If you want to filter out the tuples where all of a,b,c and d are even:
filter4allEven :: [(Int,Int,Int,Int)] -> [(Int,Int,Int,Int)]
filter4allEven [] = []
filter4allEven ((a,b,c,d):xs)
| all even [a,b,c,d] = (a,b,c,d) : filter4AllEven xs
| otherwise = filter4AllEven xs
(If the use of all confuses you, just read even a && even b && even c && even d)
And finally, here's a function that returns all the even tuple components (tuples themselves can't be even!) in the same order as they appear in the argument list:
evenTupleComponents :: [(Int,Int,Int,Int)] -> [Int]
evenTupleComponents [] = []
evenTupleComponents ((a,b,c,d):xs) = [x | x <- [a,b,c,d], even x] ++ evenTupleComponents
Once you do a couple of exercises like these, you'll see why using standard functions is a good idea, since they all follow similar patterns, like applying a function to each tuple separately, including or excluding a tuple when it has some property or, more generally, giving a base value for the empty list and a combining function for the recursive case. For instance, I would write evenTupleComponents as evenTupleComponents = filter even . concatMap (\(a,b,c,d) -> [a,b,c,d]), but that's a different story :)

How do I iterate a list?

I am trying to do basic list operations with SML.
I want to extract each element of the list and append string to that element and add it back to the list.
Example:
List : [A,B,C,D]
String : A
Final List: [AA,AB,AC,AD]
How can I iterate through each element in the list in SML? I can append strings using ^ and concatenate lists using # but how do I extract each element from the list?
Also can we use something like map or arrays to store these list values and pass it to different functions in SML?
I could just find some vague information about map and no definite information as to how we can use it.
two easy ways to do this:
- fun addstring (x::xs) a = (a^x) :: addstring xs a
= | addstring [] a = []
= ;
val addstring = fn : string list -> string -> string list
- addstring ["A", "B", "C", "D"] "A";
val it = ["AA","AB","AC","AD"] : string list
The above uses pattern matching to destruct the list, performs the operation, then constructs the list again, recursing as it goes.
- fun addstring2 xs a = map (fn x => a^x) xs;
val addstring2 = fn : string list -> string -> string list
- addstring2 ["A", "B", "C", "D"] "A";
val it = ["AA","AB","AC","AD"] : string list
This one is a fair bit simpler (if perhaps a tiny bit harder to read than the explicit cases in addstring.) but it shows how map is used - you specify a function that maps each element from the source to the target domain, give it a list of elements in the source domain, and it returns a list in the target domain.
of course, neither of these do in-place updating of the list, they return the new list.