Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using List.collect f#

I am trying to define a function which takes two lists and combines them using List.collect.

let concat xs xs' = 
    let concatList =  List.collect xs xs'
    printfn "%A" concatList

concat [1;2;3;4] [5;6;7;8]

I get the error message: FS0001: This expression was expected to have type ''a-> 'b list' but here has type ''c list'

I read that this might be due to missing parameters, but I am unsure about this.

EDIT:

So I kinda got it to work like this:

 let concat xs xs' = 
    let concatList =  List.collect (fun x -> xs @ xs') xs
    printfn "%A" concatList

concat [1;2;3;4] [5;6;7;8]

But the output is: [1; 2; 3; 4; 5; 6; 7; 8; 1 ;2 ;3 4; 5; 6; 7; 8; 1 ;2 ;3 4; 5; 6; 7; 8; 1 ;2 ;3 4; 5; 6; 7; 8;]

Only wanted it to be [1 ;2 ;3 4; 5; 6; 7; 8;] Any ideas why it runs so many times?

EDIT 2:

So I got it working like this:

let concat xs xs' = 
    let combList = [[xs];[xs']]
    let concatList =  List.collect id combList
    printfn "%A" concatList

concat [1;2;3;4] [5;6;7;8]
like image 253
DonutSteve Avatar asked Mar 11 '23 22:03

DonutSteve


1 Answers

As you noted in the comments, List.collect applies a function to each element of a list. Afterwards, it concatenates the results and returns a combined list. This second behavior is what will allow you to produce behavior similar to List.concat.

What do we need to do to achieve this?

Let's try looking at the documentation example:

let list1 = [10; 20; 30]
let collectList = List.collect (fun x -> [for i in 1..3 -> x * i]) list1
printfn "%A" collectList
//Output
//[10; 20; 30; 20; 40; 60; 30; 60; 90]

What's happening in this example is that for every element of list1, we are applying the function (fun x -> [for i in 1..3 -> x * i]). This gives us the same result as if we had used List.map. The result is [[10; 20; 30]; [20; 40; 60]; [30; 60; 90]], which is then concatenated by List.collect into the final result above.

Now as to your problem, lets consider a related problem. Let's say we are given a list of lists such as

let x = [[10; 20; 30]; [20; 40; 60]; [30; 60; 90]]

How do we use List.collect to concatenate them to get the output [10; 20; 30; 20; 40; 60; 30; 60; 90]?

So, List.collect requires a function and a list. We can pass in the list of lists defined above, x, but we still need a function that will do a map. However, we don't really want to do any transformations of the elements of x we just want to use them as is, which means we should use id. Then using

List.collect id x

will return the desired result. Your specific problem is very similar to the problem above and should not be too difficult to solve.

like image 100
Ringil Avatar answered Mar 28 '23 00:03

Ringil