As Brian noted, using @ usually problematic because an operator cannot be effectively implemented for (simple) functional lists — it needs to copy the entire first list.
I think Brians' suggestion was to write a sequence generator that would generate a list right away, but it's a little more complicated. You will need to convert the list to an array and then write something like:
let convolve yx = y |> List.map (fun ye -> x |> List.map ((*) ye) |> Array.ofList) |> List.mapi (fun il -> Array.init (2 * l.Length - 1) (fun n -> if n < i || n - i >= l.Length then 0 else l.[n - i])) |> List.reduce (Array.map2 (+))
In general, if performance is an important issue, then you will probably have to use arrays anyway (because this problem can be better solved by accessing items by index). Using arrays is a bit more complicated (you need to index correctly), but is great for F #.
In any case, if you want to write this using lists, then there are some options. You can use sequence expressions everywhere that look like this:
let convolve y (x:_ list) = [ for i, v1 in x |> List.zip [ 0 .. x.Length - 1] -> [ yield! listFill i 0 for v2 in y do yield v1 * v2 yield! listFill (x.Length - i - 1) 0 ] ] |> List.reduce (List.map2 (+))
... or you can also combine the two parameters and use the expression of the nested sequence (with yield! to generate zeros and lists) in the lambda function that you switch to List.mapi :
let convolve yx = y |> List.map (fun ye -> x |> List.map ((*) ye)) |> List.mapi (fun il -> [ for _ in 1 .. i do yield 0 yield! l for _ in 1 .. (l.Length - i - 1) do yield 0 ]) |> List.reduce (List.map2 (+))
source share