For example if there is a two-dimensional list :
let two_list = [[1;2;3];
[4;5;6];
[7;8;9]];;
how can I iterate through this list without using List modules.
With the List module you would write:
let two_list = [
[1;2;3];
[4;5;6];
[7;8;9]
]
let () =
List.iter (fun l -> List.iter print_int l) two_list
So, if you want to do the same without using the List module, all you have to do is to write your own list_iter function and use it instead of List.iter:
let two_list = [
[1;2;3];
[4;5;6];
[7;8;9]
]
let rec list_iter f = function
| [] -> ()
| hd::tail -> begin
f hd;
list_iter f tail
end
let () =
list_iter (fun l -> list_iter print_int l) two_list
Related
If I have an input of a tuple containing two lists of integers of the same length, and I want my output to be a list of these two lists zipped, after extracting these two lists from the tuple how do I zip each individual element into one list? For example, if my input is twolists= ([1;2;3], [4;5;6]), then I want my output to be [(1,4); (2,5); (3,6)]. How do I zip each element and add it to my output?
The function name and type is as follows:
let rec pairlists twolists = ...
val pairlists : 'a list * 'b list -> ('a * 'b) list = fun
So far I have:
let rec pairlists twolists =
let (l1, l2) = twolists in
let rec zip (l1,l2) =
match l1 with
|[] -> l2
|x :: xs -> x :: zip(l2, xs) in
twolists ;;
but this is clearly not doing what I want.
Are you looking for List.combine ?
val combine : 'a list -> 'b list -> ('a * 'b) list
Transform a pair of lists into a list of pairs: combine [a1; ...; an] [b1; ...; bn] is [(a1,b1); ...; (an,bn)].
Raises Invalid_argument if the two lists have different lengths. Not tail-recursive.
If your result list should contain elements that consist of the elements of both sublists, then you obviously have to destructure each sublist on each iteration.
If the lists are guaranteed to have the same lengths, the solution can be as simple as:
let rec zip paired_lists =
match paired_lists with
| [], [] -> []
| h1::t1, h2::t2 -> (h1, h2)::(zip (t1, t2))
| _, _ -> failwith "oops, the lists seems to have different lengths"
;;
zip ([1;2;3], [4;5;6]);;
- : (int * int) list = [(1, 4); (2, 5); (3, 6)]
But this one is not tail-recursive, which is obviously not good. The second sub-optimal thing is this reconstruction of tuple of lists on each iteration (I'm a newbie in OCaml, so chances are compiler is smart enough to avoid the unnecessary allocations, but still...). Fixing both flaws is trivial too:
let zip_tr paired_lists =
let list1, list2 = paired_lists in
let rec aux l1 l2 acc =
match l1, l2 with
| [], [] -> List.rev acc
| h1::t1, h2::t2 -> aux t1 t2 (h1, h2)::acc
| _, _ -> failwith "oops, the lists seems to have different lengths"
in aux list1 list2 []
;;
zip_tr ([1;2;3], [4;5;6]);;
- : (int * int) list = [(1, 4); (2, 5); (3, 6)]
The signature of your code does not match the expected signature :
line 2, characters 11-13:
Warning 26: unused variable l2.
Line 2, characters 7-9:
Warning 26: unused variable l1.
val pairlists : 'a list * 'a list -> 'a list = <fun>
Indeed, both possible matches return either a 'a list (this is l2) or x::zip... which is also a list of 'a type.
There should be sth like (x,y)::list in your code.
In addition, pairlists is not recursive and does not need to be declared as such, only zip is recursive.
The end of your function shall be like this (otherwise zip has no effect) :
....
let rec zip (l1,l2) =
match l1 with
|[] -> l2
|x :: xs -> x :: zip(l2, xs) in
zip twolists ;;
In addition to the other solutions mentioned, ocaml-4.08 onwards enables you to provide let+ and and+ operators which will zip a list sum-wise, where you might otherwise think of using applicatives. Whether it is an improvement on them is in the eye of the beholder:
let (let+) list f = List.map f list
let (and+) a b =
let rec loop first second =
match first,second with
first_hd::first_tl,second_hd::second_tl ->
(first_hd,second_hd)::(loop first_tl second_tl)
| _ -> []
in
loop a b
let pairlists = function
first,second ->
let+ elt1 = first
and+ elt2 = second in
[elt1 ; elt2]
(* example *)
let () =
let res = pairlists ([1;2;3], [4;5;6]) in
List.iter
(fun list -> List.iter (fun i -> Printf.printf "%d " i) list ;
print_endline "")
res
Here by way of comparison is the more traditional approach if you are using applicatives
let pure x = [x]
let (<*>) aps args =
List.concat (List.map (fun f -> List.map (fun x -> f x) args) aps)
let (<|>) aps args =
let rec loop args_rest aps_rest =
match args_rest,aps_rest with
args_hd::args_tl,aps_hd::aps_tl ->
(aps_hd args_hd)::(loop args_tl aps_tl)
| _ -> []
in
loop args aps
let pairlists = function
first,second ->
let two_list a b = a :: [b] in
pure two_list <*> first <|> second
(* example *)
let () =
let res = pairlists ([1;2;3], [4;5;6]) in
List.iter
(fun list -> List.iter (fun i -> Printf.printf "%d " i) list ;
print_endline "")
res
From pseudo C#, I have this:
class C
{
List<A> a;
List<B> b;
}
List<C> L;
I would like to get to get two lists: ListA and ListB where ListA is the concatenation of all 'a' fields from the list L, and similar for ListB.
it would be something like:
var ListA = new List<A>();
var ListB = new List<B>();
foreach (var l in L)
{
ListA.Append(l.a);
ListB.Append(l.b);
}
In F#,
I assume it would be something like: let ListA = L |> List.Concat (but how do I say to pick the field a?)
or could it be done as a let ListA = L |> List.Fold (fun acc value -> acc.Concat value) (how do I specify the empty list here?)
or, can it be done like this?
let getElementsA (l : C list) =
seq {
for element in l do
for a in element.a do
yield a
}
but isn't that too verbose?
This is what List.collect, or Seq.collect for C# lists, is for:
let listA = l |> Seq.collect (fun element -> element.a) |> List.ofSeq
let listB = l |> Seq.collect (fun element -> element.b) |> List.ofSeq
Or if you really need to do it in one iteration you can use a fold:
let (seqA, seqB) =
l |> Seq.fold
(fun (seqA, seqB) element -> (Seq.append element.a seqA, Seq.append element.b seqB))
([], [])
You can use List.collect:
let getElementsA (cs : C list) = cs |> List.collect (fun c -> c.a)
if the property type is System.Collection.List<T> then you can use Seq.collect:
let getElementsA (cs : C list) = cs |> Seq.collect (fun c -> c.AS)
this returns a A seq which you can convert into a list using List.ofSeq:
let getElementsA (cs : C list) = cs |> Seq.collect (fun c -> c.AS) |> List.ofSeq
F# uses other lists, function objects (like delegates). You can find all that you need in Microsoft.FSharp namespace
If I have this code in F#.
A function that resives a list with action and return nothing (list:'a list -> action:('a -> unit) -> unit).
module FS =
let actLit list action =
list
|> List.iter (action)
For this on C#, include Microsoft.FSharp.Collections.ListModule module and call functions work with F# lists. ListModule.OfSeq(l) creates new F# list.
Microsoft.FSharp.Core.FunctionModule contains conversion methods.
After converting you can call it.
var a = new List<int> ();
var list = ListModule.OfSeq(a);
var func = FuncConvert.FromAction<int>(Console.WriteLine);
FS.actLit(list, func);
fold_right gives me values starting from the tail of the list but I want to give a function to fold_right as a parameter such that this function would collect values starting from the head of the list .
I want iterto receive values starting with the head of the list.
Continous Passing is the keyword ... .Another way to ask the question would be how tofold_leftwith fold_right
let fold f ls acc = List.fold_right f ls acc
val iter : ('a -> unit) -> 'a t -> unit
let iter f my_type =
let rec iiter my_type return =
return (fold (fun x y -> f x) my_type ()) () in iiter my_type (fun x y -> ())
But when I call :
iter (fun a -> print_string a) ["hi";"how";"are";"you"];;
Output:
youarehowhi
I need
hihowareyou
This is quite simple, you must try to match the signatures for the behavior.
Iteration takes no input, and returns unit, while folding takes an input and returns an output of the same type. Now, if the input taken by folding is unit then you'll have a folding function which applies a function on each element of a collection by passing an additional unit and returning an unit, which basically corresponds to the normal iteration, eg:
# let foo = [1;2;3;4;5];;
# List.fold_left (fun _ a -> print_int a; ()) () foo;;
12345- : unit = ()
As you can see the fold function just ignores the first argument, and always returns unit.
let fold_left f init ls =
let res = List.fold_right (fun a b acc -> b (f acc a)) ls (fun a -> a)
in res init
now calling
fold_left (fun a b -> Printf.printf "%s\n" b) () ["how";"are";"you"];;
gives us
how
are
you
fold_left is like List.fold_left but constructed with List.fold_right (Not tail-recursive):
let fold_left f a l = List.fold_right (fun b a -> f a b) (List.rev l) a ;;
Is not a good idea, because fold_left is not tail-recursive and List.fold_left is tail-recursive. Is better to produce a fold_right (tail-recursive) as :
let fold_right f l a = List.fold_left (fun a b -> f b a) a (List.rev l) ;;
If you can't use List.rev :
let rev l =
let rec aux acc = function
| [] -> acc
| a::tl -> aux (a::acc) tl
in
aux [] l
;;
iter use fold_left :
let iter f op = ignore (fold_left (fun a b -> f b;a) [] op ) ;;
Test :
# fold_left (fun a b -> (int_of_string b)::a ) [] ["1";"3"];;
- : int list = [3; 1]
# rev [1;2;3];;
- : int list = [3; 2; 1]
# iter print_string ["hi";"how";"are";"you"];;
hihowareyou- : unit = ()
The continuation that you need to pass through fold in this case is a function that will, once called, iterate through the rest of the list.
EDIT: like so:
let iter f list = fold
(fun head iter_tail -> (fun () -> f head;; iter_tail ()))
list
()
I am new to programming in functional languages. I am attempting to implement the F# collect for list.
let rec collect func list =
match list with
| [] -> []
| hd::tl -> let tlResult = collect func tl
func hd::tlResult;;
collect (fun x -> [for i in 1..3 -> x * i]) [1;2;3];;
should print:
val it : int list = [1; 2; 3; 2; 4; 6; 3; 6; 9]
but I got:
val it : int list = [[1; 2; 3;], [2; 4; 6;], [3; 6; 9]]
Here's a tail recursive collect that won't stack overflow for large lists.
let collect f xs =
let rec prepend res xs = function
| [] -> loop res xs
| y::ys -> prepend (y::res) xs ys
and loop res = function
| [] -> List.rev res
| x::xs -> prepend res xs (f x)
loop [] xs
A simpler version, that's somewhat cheating, is:
let collect (f: _ -> list<_>) (xs: list<_>) = [ for x in xs do yield! f x ]
The collect function is tricky to implement efficiently in the functional style, but you can quite easily implement it using the # operator that concatenates lists:
let rec collect f input =
match input with
| [] -> []
| x::xs -> (f x) # (collect f xs)
I am new to F# and trying to figure out some basics but am stumbling along slowly. In the code below I am trying to generate a list of random integers and then sorting it.
let randomNumberList count =
let r = System.Random()
List.init count (fun _ -> r.Next(100))
let rec selectionSort l = function
| [] -> []
| l -> let min = List.min l in
let rest = List.filter (fun i -> i <> min) l in
let sortedList = selectionSort rest in
min :: sortedList
sortedList = selectionSort l
let unsortedList = randomNumberList 10
printfn "%A" unsortedList
printfn "%A" sortedList
So two things...one is the error I'm getting:
stdin(515,19): error FS0001: This expression was expected to have type
'a list
but here has type
'a list -> 'a list
The other is with the random number list. It works, but I want the numbers generated to be less than 100, instead of the massive values I'm getting now.
Thanks for your patience and help!
As mentioned in the comment, there is no need for l in let rec selectionSort. Fixed code:
let randomNumberList count =
let r = System.Random()
List.init count (fun _ -> r.Next(100))
let rec selectionSort = function
| [] -> []
| l -> let min = List.min l in
let rest = List.filter (fun i -> i <> min) l in
let sortedList = selectionSort rest in
min :: sortedList
let unsortedList = randomNumberList 10
let sortedList = selectionSort unsortedList
printfn "%A" unsortedList
printfn "%A" sortedList
System.Console.ReadLine() |> ignore
Explanation:
let vname = function
| ... -> ...
| ... -> ...
is the short form of
let vname arg = match arg with
| ... -> ...
| ... -> ...