F# Matching results of recursive calls using higher order functions - f#

Given a simple function, where we do pattern matching on the result of a recursive call, such as:
let rec sumProd = function
| [] -> (0,1)
| x::rest -> let (rSum,rProd) = sumProd rest
(x + rSum,x * rProd)
sumProd [2;5] //Expected (7, 10)
How would I go about changing it into something using higher order functions, e.g. foldBack?
let sumProdHigherOrder lst =
List.foldBack (fun x acc -> (acc + x, acc * x)) lst (0,0)
The above seemed almost like the way to do it, but calling it gives the error: The type 'int' does not match the type 'int * int'
sumProdHigherOrder [2;5] //Expected (7, 10)
What am I missing?

Your missing the tuple functions fst and snd:
List.foldBack (fun x acc -> (fst acc + x, snd acc * x)) [2;5] (0,1)
// val it : int * int = (7, 10)
Or even better, decomposing the tuple at the lambda. I see you just found it:
List.foldBack (fun x (s, m) -> (s + x, m * x)) [2;5] (0,1)
Also note that since the operations are commutative you can do a straight fold:
List.fold (fun (s, m) x -> (s + x, m * x)) (0,1) [2;5]
It will be more efficient.

Right! Of course it shouldn't be the same accumulator that gets passed through the list. After staring intensely at the code for some minutes, I figured it out:
let sumProdHigherOrder lst =
List.foldBack (fun x (acc,acc') -> (acc + x, acc' * x)) lst (0,1)

Related

F#, implement fold3, fold4, fold_n

I am interested to implement fold3, fold4 etc., similar to List.fold and List.fold2. e.g.
// TESTCASE
let polynomial (x:double) a b c = a*x + b*x*x + c*x*x*x
let A = [2.0; 3.0; 4.0; 5.0]
let B = [1.5; 1.0; 0.5; 0.2]
let C = [0.8; 0.01; 0.001; 0.0001]
let result = fold3 polynomial 0.7 A B C
// 2.0 * (0.7 ) + 1.5 * (0.7 )^2 + 0.8 * (0.7 )^3 -> 2.4094
// 3.0 * (2.4094) + 1.0 * (2.4094)^2 + 0.01 * (2.4094)^3 -> 13.173
// 4.0 * (13.173) + 0.5 * (13.173)^2 + 0.001 * (13.173)^3 -> 141.75
// 5.0 * (141.75) + 0.2 * (141.75)^2 + 0.0001 * (141.75)^3 -> 5011.964
//
// Output: result = 5011.964
My first method is grouping the 3 lists A, B, C, into a list of tuples, and then apply list.fold
let fold3 f x A B C =
List.map3 (fun a b c -> (a,b,c)) A B C
|> List.fold (fun acc (a,b,c) -> f acc a b c) x
// e.g. creates [(2.0,1.5,0.8); (3.0,1.0,0.01); ......]
My second method is to declare a mutable data, and use List.map3
let mutable result = 0.7
List.map3 (fun a b c ->
result <- polynomial result a b c // Change mutable data
// Output intermediate data
result) A B C
// Output from List.map3: [2.4094; 13.17327905; 141.7467853; 5011.963942]
// result mutable: 5011.963942
I would like to know if there are other ways to solve this problem. Thank you.
For fold3, you could just do zip3 and then fold:
let polynomial (x:double) (a, b, c) = a*x + b*x*x + c*x*x*x
List.zip3 A B C |> List.fold polynomial 0.7
But if you want this for the general case, then you need what we call "applicative functors".
First, imagine you have a list of functions and a list of values. Let's assume for now they're of the same size:
let fs = [ (fun x -> x+1); (fun x -> x+2); (fun x -> x+3) ]
let xs = [3;5;7]
And what you'd like to do (only natural) is to apply each function to each value. This is easily done with List.map2:
let apply fs xs = List.map2 (fun f x -> f x) fs xs
apply fs xs // Result = [4;7;10]
This operation "apply" is why these are called "applicative functors". Not just any ol' functors, but applicative ones. (the reason for why they're "functors" is a tad more complicated)
So far so good. But wait! What if each function in my list of functions returned another function?
let f1s = [ (fun x -> fun y -> x+y); (fun x -> fun y -> x-y); (fun x -> fun y -> x*y) ]
Or, if I remember that fun x -> fun y -> ... can be written in the short form of fun x y -> ...
let f1s = [ (fun x y -> x+y); (fun x y -> x-y); (fun x y -> x*y) ]
What if I apply such list of functions to my values? Well, naturally, I'll get another list of functions:
let f2s = apply f1s xs
// f2s = [ (fun y -> 3+y); (fun y -> 5+y); (fun y -> 7+y) ]
Hey, here's an idea! Since f2s is also a list of functions, can I apply it again? Well of course I can!
let ys = [1;2;3]
apply f2s ys // Result: [4;7;10]
Wait, what? What just happened?
I first applied the first list of functions to xs, and got another list of functions as a result. And then I applied that result to ys, and got a list of numbers.
We could rewrite that without intermediate variable f2s:
let f1s = [ (fun x y -> x+y); (fun x y -> x-y); (fun x y -> x*y) ]
let xs = [3;5;7]
let ys = [1;2;3]
apply (apply f1s xs) ys // Result: [4;7;10]
For extra convenience, this operation apply is usually expressed as an operator:
let (<*>) = apply
f1s <*> xs <*> ys
See what I did there? With this operator, it now looks very similar to just calling the function with two arguments. Neat.
But wait. What about our original task? In the original requirements we don't have a list of functions, we only have one single function.
Well, that can be easily fixed with another operation, let's call it "apply first". This operation will take a single function (not a list) plus a list of values, and apply this function to each value in the list:
let applyFirst f xs = List.map f xs
Oh, wait. That's just map. Silly me :-)
For extra convenience, this operation is usually also given an operator name:
let (<|>) = List.map
And now, I can do things like this:
let f x y = x + y
let xs = [3;5;7]
let ys = [1;2;3]
f <|> xs <*> ys // Result: [4;7;10]
Or this:
let f x y z = (x + y)*z
let xs = [3;5;7]
let ys = [1;2;3]
let zs = [1;-1;100]
f <|> xs <*> ys <*> zs // Result: [4;-7;1000]
Neat! I made it so I can apply arbitrary functions to lists of arguments at once!
Now, finally, you can apply this to your original problem:
let polynomial a b c (x:double) = a*x + b*x*x + c*x*x*x
let A = [2.0; 3.0; 4.0; 5.0]
let B = [1.5; 1.0; 0.5; 0.2]
let C = [0.8; 0.01; 0.001; 0.0001]
let ps = polynomial <|> A <*> B <*> C
let result = ps |> List.fold (fun x f -> f x) 0.7
The list ps consists of polynomial instances that are partially applied to corresponding elements of A, B, and C, and still expecting the final argument x. And on the next line, I simply fold over this list of functions, applying each of them to the result of the previous.
You could check the implementation for ideas:
https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/array.fs
let fold<'T,'State> (f : 'State -> 'T -> 'State) (acc: 'State) (array:'T[]) =
checkNonNull "array" array
let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
let mutable state = acc
for i = 0 to array.Length-1 do
state <- f.Invoke(state,array.[i])
state
here's a few implementations for you:
let fold2<'a,'b,'State> (f : 'State -> 'a -> 'b -> 'State) (acc: 'State) (a:'a array) (b:'b array) =
let mutable state = acc
Array.iter2 (fun x y->state<-f state x y) a b
state
let iter3 f (a: 'a[]) (b: 'b[]) (c: 'c[]) =
let f = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f)
if a.Length <> b.Length || a.Length <> c.Length then failwithf "length"
for i = 0 to a.Length-1 do
f.Invoke(a.[i], b.[i], c.[i])
let altIter3 f (a: 'a[]) (b: 'b[]) (c: 'c[]) =
if a.Length <> b.Length || a.Length <> c.Length then failwithf "length"
for i = 0 to a.Length-1 do
f (a.[i]) (b.[i]) (c.[i])
let fold3<'a,'b,'State> (f : 'State -> 'a -> 'b -> 'c -> 'State) (acc: 'State) (a:'a array) (b:'b array) (c:'c array) =
let mutable state = acc
iter3 (fun x y z->state<-f state x y z) a b c
state
NB. we don't have an iter3, so, implement that. OptimizedClosures.FSharpFunc only allow up to 5 (or is it 7?) params. There are a finite number of type slots available. It makes sense. You can go higher than this, of course, without using the OptimizedClosures stuff.
... anyway, generally, you don't want to be iterating too many lists / arrays / sequences at once. So I'd caution against going too high.
... the better way forward in such cases may be to construct a record or tuple from said lists / arrays, first. Then, you can just use map and iter, which are already baked in. This is what zip / zip3 are all about (see: "(array1.[i],array2.[i],array3.[i])")
let zip3 (array1: _[]) (array2: _[]) (array3: _[]) =
checkNonNull "array1" array1
checkNonNull "array2" array2
checkNonNull "array3" array3
let len1 = array1.Length
if len1 <> array2.Length || len1 <> array3.Length then invalidArg3ArraysDifferent "array1" "array2" "array3" len1 array2.Length array3.Length
let res = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked len1
for i = 0 to res.Length-1 do
res.[i] <- (array1.[i],array2.[i],array3.[i])
res
I'm working with arrays at the moment, so my solution pertained to those. Sorry about that. Here's a recursive version for lists.
let fold3 f acc a b c =
let mutable state = acc
let rec fold3 f a b c =
match a,b,c with
| [],[],[] -> ()
| [],_,_
| _,[],_
| _,_,[] -> failwith "length"
| ahead::atail, bhead::btail, chead::ctail ->
state <- f state ahead bhead chead
fold3 f atail btail ctail
fold3 f a b c
i.e. we define a recursive function within a function which acts upon/mutates/changes the outer scoped mutable acc variable (a closure in functional speak). Finally, this gets returned.
It's pretty cool how much type information gets inferred about these functions. In the array examples above, mostly I was explicit with 'a 'b 'c. This time, we let type inference kick in. It knows we're dealing with lists from the :: operator. That's kind of neat.
NB. the compiler will probably unwind this tail-recursive approach so that it is just a loop behind-the-scenes. Generally, get a correct answer before optimising. Just mentioning this, though, as food for later thought.
I think the existing answers provide great options if you want to generalize folding, which was your original question. However, if I simply wanted to call the polynomial function on inputs specified in A, B and C, then I would probably do not want to introduce fairly complex constructs like applicative functors with fancy operators to my code base.
The problem becomes a lot easier if you transpose the input data, so that rather than having a list [A; B; C] with lists for individual variables, you have a transposed list with inputs for calculating each polynomial. To do this, we'll need the transpose function:
let rec transpose = function
| (_::_)::_ as M -> List.map List.head M :: transpose (List.map List.tail M)
| _ -> []
Now you can create a list with inputs, transpose it and calculate all polynomials simply using List.map:
transpose [A; B; C]
|> List.map (function
| [a; b; c] -> polynomial 0.7 a b c
| _ -> failwith "wrong number of arguments")
There are many ways to solve this problem. Few are mentioned like first zip3 all three list, then run over it. Using Applicate Functors like Fyodor Soikin describes means you can turn any function with any amount of arguments into a function that expects list instead of single arguments. This is a good general solution that works with any numbers of lists.
While this is a general good idea, i'm sometimes shocked that so few use more low-level tools. In this case it is a good idea to use recursion and learn more about recursion.
Recursion here is the right-tool because we have immutable data-types. But you could consider how you would implement it with mutable lists and looping first, if that helps. The steps would be:
You loop over an index from 0 to the amount of elements in the lists.
You check if every list has an element for the index
If every list has an element then you pass this to your "folder" function
If at least one list don't have an element, then you abort the loop
The recursive version works exactly the same. Only that you don't use an index to access the elements. You would chop of the first element from every list and then recurse on the remaining list.
Otherwise List.isEmpty is the function to check if a List is empty. You can chop off the first element with List.head and you get the remaining list with the first element removed by List.tail. This way you can just write:
let rec fold3 f acc l1 l2 l3 =
let h = List.head
let t = List.tail
let empty = List.isEmpty
if (empty l1) || (empty l2) && (empty l3)
then acc
else fold3 f (f acc (h l1) (h l2) (h l3)) (t l1) (t l2) (t l3)
The if line checks if every list has at least one element. If that is true
it executes: f acc (h l1) (h l2) (h l3). So it executes f and passes it the first element of every list as an argument. The result is the new accumulator of
the next fold3 call.
Now that you worked on the first element of every list, you must chop off the first element of every list, and continue with the remaining lists. You achieve that with List.tail or in the above example (t l1) (t l2) (t l3). Those are the next remaining lists for the next fold3 call.
Creating a fold4, fold5, fold6 and so on isn't really hard, and I think it is self-explanatory. My general advice is to learn a little bit more about recursion and try to write recursive List functions without Pattern Matching. Pattern Matching is not always easier.
Some code examples:
fold3 (fun acc x y z -> x + y + z :: acc) [] [1;2;3] [10;20;30] [100;200;300] // [333;222;111]
fold3 (fun acc x y z -> x :: y :: z :: acc) [] [1;2;3] [10;20;30] [100;200;300] // [3; 30; 300; 2; 20; 200; 1; 10; 100]

Arithmetic with decimal option types

I'm trying to do some mathematical operations with decimal options on a custom type:
type LineItem = {Cost: decimal option; Price: decimal option; Qty: decimal option}
let discount = 0.25M
let createItem (c, p, q) =
{Cost = c; Price = p; Qty = q}
let items =
[
(Some 1M , None , Some 1M)
(Some 3M , Some 2.0M , None)
(Some 5M , Some 3.0M , Some 5M)
(None , Some 1.0M , Some 2M)
(Some 11M , Some 2.0M , None)
]
|> List.map createItem
I can do some very simple arithmetic with
items
|> Seq.map (fun line -> line.Price
|> Option.map (fun x -> discount * x))
which gives me
val it : seq<decimal option> =
seq [null; Some 0.500M; Some 0.750M; Some 0.250M; ...]
If I try to actually calculate the thing I need
items
|> Seq.map (fun line -> line.Price
|> Option.map (fun x -> discount * x)
|> Option.map (fun x -> x - (line.Cost
|> Option.map (fun x -> x)))
|> Option.map (fun x -> x * (line.Qty
|> Option.map (fun x -> x))))
I get the error
error FS0001: Type constraint mismatch. The type
'a option
is not compatible with type
decimal
The type ''a option' is not compatible with the type 'decimal'
where I would have expected a seq<decimal option>.
I must be missing something but I can't seem to spot whatever it is I'm missing.
You are mixing decimal with decimal option.
If you're trying to solve everything with Option.map you may want to try with Option.bind instead, so your code will be 'linearly nested':
items
|> Seq.map (
fun line ->
Option.bind(fun price ->
Option.bind(fun cost ->
Option.bind(fun qty ->
Some ((discount * price - cost ) * qty)) line.Qty) line.Cost) line.Price)
which can be an interesting exercise, especially if you want to understand monads, then you will be able to use a computation expression, you can create your own or use one from a library like F#x or F#+:
open FSharpPlus.Builders
items |> Seq.map (fun line ->
monad {
let! price = line.Price
let! cost = line.Cost
let! qty = line.Qty
return ((discount * price - cost ) * qty)
}
)
but if you link F#+ you'll have Applicative Math Operators available:
open FSharpPlus.Operators.ApplicativeMath
items |> Seq.map (fun line -> ((discount *| line.Price) |-| line.Cost ) |*| line.Qty)
That's nice stuff to learn but otherwise I would suggest to use F# built-in features instead, like pattern-match, it would be easier:
items
|> Seq.map (fun line -> match line.Price, line.Qty, line.Cost with
| Some price, Some qty, Some cost ->
Some ((discount * price - cost ) * qty)
| _ -> None)
Then since you can also pattern-match over records it can be further reduced to:
items
|> Seq.map (function
| {Cost = Some cost; Price = Some price; Qty = Some qty} ->
Some ((discount * price - cost ) * qty)
| _ -> None)
Note that Option.map (fun x -> x) doesn't transform anything.
One problem you have is the following code:
(line.Cost |> Option.map (fun x -> x))
The lambda function (fun x -> x) already exists. This is the id function. It just returns whatever you have unchanged. You also could write the code you have like this:
(line.Cost |> Option.map id)
And the next thing. Mapping over the id function makes no sense. You unwrap whatever is inside the option, apply the id function to it. What didn't change the decimal at all. Then you wrap the decimal again in an option. You also can just write:
line.Cost
and completely remove the Option.map as it does nothing.
So the code you have here:
|> Option.map (fun x -> x - (line.Cost |> Option.map (fun x -> x)))
is identical to:
|> Option.map (fun x -> x - line.Cost)
This obviously does not work because here you try to subtract x a decimal with line.Cost a option decimal. So you get a type-error.
I guess what you really want to do is to subtract line.Cost from line.Price if line.Cost is present, otherwise you want to preserve line.Price unchanged.
One way would be just to provide a default value for line.Costs that can be used and have no effect on the subtraction. For example you could use the value 0 for subtraction if line.Costs is None.
So you also could write something like this instead:
|> Option.map (fun x -> x - (defaultArg line.Cost 0m))
A default value for multiplication would be 1m. So you overall end with.
items
|> Seq.map (fun line ->
line.Price
|> Option.map (fun x -> discount * x)
|> Option.map (fun x -> x - (defaultArg line.Cost 0m))
|> Option.map (fun x -> x * (defaultArg line.Qty 1m)))
The above code for example returns:
[None; Some -2.500M; Some -21.250M; Some 0.500M; Some -10.500M]
If your goal is that a whole computation turns into None as soon a single
value is None. I would just add map2 as a helper function.
module Option =
let map2 f x y =
match x,y with
| Some x, Some y -> Some (f x y)
| _ -> None
then you just can write:
items
|> List.map (fun line ->
line.Price
|> Option.map (fun price -> price * discount)
|> Option.map2 (fun cost price -> price - cost) line.Cost
|> Option.map2 (fun qty price -> price * qty) line.Qty)
and it will return:
[None; None; Some -21.250M; None; None]
Within the Option.map the x is actually a decimal, but the signature for Option.map is 'T option -> 'U option. So here:
Option.map (fun x -> x - (line.Cost |> Option.map (fun x -> x)))
you have the following:
Option.map (fun x -> /*decimal*/ x - /*decimal option*/(line.Cost |> Option.map (fun x -> x)))
So the decimal option has to be converted to decimal to be compatible with what's in the first Option.map. But now you have to deal with None result.
Below a quick (and nasty) fix that just is using an if statement to extract Value (which will be a decimal) or if None then return 0.
items
|> Seq.map (fun line -> line.Price
|> Option.map (fun x -> discount * x)
|> Option.map (fun x -> x - if line.Cost.IsSome then line.Cost.Value else 0m)
|> Option.map (fun x -> x * if line.Qty.IsSome then line.Qty.Value else 0m))
For a more sophisticated solution I recommend this answer.
For completeness sake, you may also leverage the monadic properties of the option type by "lifting" the values outside of the option. This is a somewhat simpler variant of the applicative approach linked by #PiotrWolkowski and those shown by #Gustavo. Applicatives not only wrap values in the monad, but also the functions applied to them.
We start by making the option type amenable to monadic operations in terms of bind and return. Thankfully, those functions are already defined, there's only a little tweak in the argument order.
let (>>=) ma f = Option.bind f ma
let ``return`` = Some
On top of this there's the lift function and a couple of operators for convenience. If needed, they could be generalized by marking them inline.
let liftOpt op x y =
x >>= fun a ->
y >>= fun b ->
``return`` (op a b)
let (.*) = liftOpt (*)
let (.-) = liftOpt (-)
Now your calculation becomes
items
|> Seq.map (fun line ->
(line.Price .* Some discount .- line.Cost) .* line.Qty )
|> Seq.iter (printfn "%A")
which will print
<null>
<null>
Some -21.250M
<null>
<null>

F# Polynomial Derivator

I'm writing a program that takes a polynomial and returns its derivative. The polynomial is passed as predefined type "poly", which is a list of tuples in which the first element is a float representing a coefficient, and the second is an integer representing the degree of that term. So a poly p = [(2.0, 3);(1.5,2);(3.2;1)] would represent 2x^3 + 1.5x^2 + 3.2x^1. My code is as follows:
let rec diff (p:poly):poly =
match p with
| [] -> raise EmptyList
| [a]-> (fst a * snd a, snd a - 1)
| x::xs -> ((fst x * snd x), (snd x - 1)) :: diff xs
The error I'm getting tells me that the program expects the function to return a type poly, but here has the type 'a * 'b. I don't see why thats the case, when in my base case I return a tuple and in all other situations I'm appending onto an accumulating list. I've played around with the brackets, to no avail. Why is my code tossing this error?
All input is appreciated on the matter.
you said it yourself: in the base case you are returning a tuple not a list - so the inference thinks this is what you want
Just change it into:
let rec diff (p:poly):poly =
match p with
| [] -> raise EmptyList
| [a]-> [fst a * snd a, snd a - 1]
| x::xs -> ((fst x * snd x), (snd x - 1)) :: diff xs
and it should be fine (just replace the (..) with [..] ;) )
remember: :: will cons a new head onto a list
there are a few issues with float vs. int there so I would suggest this (using recursion):
type Poly = (float*int) list
let test : Poly = [(2.0, 3);(1.5,2);(3.2,1);(1.0,0)]
let rec diff (p:Poly):Poly =
match p with
| [] -> []
| x::xs -> (fst x * float (snd x), snd x - 1) :: diff xs
which is really just this:
let diff : Poly -> Poly =
List.map (fun x -> fst x * float (snd x), snd x - 1)
and can look a lot nicer without fst and snd:
let diff : Poly -> Poly =
List.map (fun (a,p) -> a * float p, p - 1)

Why does the pipe operator work?

If the pipe operator is created like this:
let (|>) f g = g f
And used like this:
let result = [2;4;6] |> List.map (fun x -> x * x * x)
Then what it seems to do is take List.Map and puts it behind (fun x -> x * x * x)
And doesn't change anything about the position of [2;4;6]
So now it looks like this:
let result2 = [2;4;6] (fun x -> x * x * x) List.map
However this doesn't work.
I am just learning f# for the first time now. And this bothered me while reading a book about f#. So I might learn what I'm missing later but I decided to ask anyway.
It is obvious though that I am missing something major. Since I can easily recreate the pipe operator. But I don't get why it works. I might embarrass myself very soon as I learn more. Oh well.
The pipe operator is simply syntactic sugar for chained method calls. It's very similar to how linq expressions are expressed in C#.
Explanation from here:
Forward Pipe Operator
I love this guy. The Forward pipe operator is simply defined as:
let (|>) x f = f x
And has a type signature:
'a -> ('a -> 'b) -> 'b
Which translates to: given a generic type 'a, and a function which takes an 'a and returns a 'b, then return the application of the function on the input.
Rather than explaining this, let me give you an example of where it can be used:
// Take a number, square it, then convert it to a string, then reverse that string
let square x = x * x
let toStr (x : int) = x.ToString()
let rev (x : string) = new String(Array.rev (x.ToCharArray()))
// 512 -> 1024 -> "1024" -> "4201"
let result = rev (toStr (square 512))
The code is very straight forward, but notice just how unruly the syntax looks. All we want to do is take the result of one computation and pass that to the next computation. We could rewrite it by introducing a series of new variables:
let step1 = square 512
let step2 = toStr step1
let step3 = rev step2
let result = step3
But now you need to keep all those temporary variables straight. What the (|>) operator does is take a value, and 'forward it' to a function, essentially allowing you to specify the parameter of a function before the function call. This dramatically simplifies F# code by allowing you to pipe functions together, where the result of one is passed into the next. So to use the same example the code can be written clearly as:
let result = 512 |> square |> toStr |> rev
Edit:
In F# what you're really doing with a method call is taking a function and then applying it to the parameter that follows, so in your example it would be List.map (fun x -> x * x * x) is applied to [2;4;6]. All that the pipe operator does is take the parameters in reverse order and then do the application reversing them back.
function: List.map (fun x -> x * x * x)
parameter: [2;4;6]
Standard F# call syntax: f g
Reversed F# call syntax: g f
Standard:
let var = List.map (fun x -> x * x * x) [2;4;6]
Reversed:
let var = [2;4;6] |> List.map (fun x -> x * x * x)
The brackets around |> mean it is an infix operator so your example could be written
let result = (|>) [2;4;6] (List.map (fun x -> x * x * x))
Since |> applies its first argument to the second, this is equivalent to
let result = (List.map (fun x -> x * x)) [2;4;6]
As others have said above, basically you're misunderstanding what result2 would resolve to. It would actually resolve to
List.map (fun x -> x * x * x) [2;4;6]
List.map takes two arguments: a function to apply to all elements in a list and a list. (fun x -> x * x * x) is the first argument and [2;4;6] is the second.
Basically just put what's on the left of |> after the end of what's on the right.
If you enter your definition of |> into fsi and look at the operator's signature derived by type inference you'll notice val ( |> ) : 'a -> ('a -> 'b) -> 'b, i.e. argument 'a being given to function ('a -> 'b) yields 'b.
Now project this signature onto your expression [2;4;6] |> List.map (fun x -> x * x * x) and you'll get List.map (fun x -> x * x * x) [2;4;6], where the argument is list [2;4;6] and the function is partially applied function of one argument List.map (fun x -> x * x * x).

How to apply Seq map function?

I been recently playing with F# . I was wondering instead of using a for loop to generate a sequence to element which are multiplied with every other element in the list how can I use a Seq map function or something similar to generate something like below.
So for e.g. I have a list [1..10] I would like to apply a fun which generates a result something like
[(1*1); (1*2);(1*3); (1*4); (1*5)......(2*1);(2*2);(2*3).....(3*1);(3*2)...]
How can i achieve this ?.
Many thanks for all you help.
let list = [1..10]
list |> List.map (fun v1 -> List.map (fun v2 -> (v1*v2)) list) |> List.collect id
The List.collect at the end flattens the list of lists.
It works the same with Seq instead of List, if you want a lazy sequence.
Or, using collect as the main iterator, as cfern suggested and obsessivley eliminating anonymous functions:
let flip f x y = f y x
let list = [1..10]
list |> List.collect ((*) >> ((flip List.map) list))
A list comprehension would be the easiest way to do this:
let allpairs L =
[for x in L do
for y in L -> (x*y)]
Or, without using any loops:
let pairs2 L = L |> List.collect (fun x -> L |> List.map (fun y -> (x*y)))
Edit in response to comment:
You could add a self-crossing extension method to a list like this:
type Microsoft.FSharp.Collections.List<'a> with
member L.cross f =
[for x in L do
for y in L -> f x y]
Example:
> [1;2;3].cross (fun x y -> (x,y));;
val it : (int * int) list =
[(1, 1); (1, 2); (1, 3); (2, 1); (2, 2); (2, 3); (3, 1); (3, 2); (3, 3)]
I wouldn't use an extension method in F# myself, is feels a bit C#'ish. But that's mostly because I don't feel that a fluent syntax is needed in F# because I usually chain my functions together with pipe (|>) operators.
My approach would be to extend the List module with a cross function, not the type itself:
module List =
let cross f L1 L2 =
[for x in L1 do
for y in L2 -> f x y]
If you do this, you can use the cross method like any other method of List:
> List.cross (fun x y -> (x,y)) [1;2;3] [1;2;3];;
val it : (int * int) list =
[(1, 1); (1, 2); (1, 3); (2, 1); (2, 2); (2, 3); (3, 1); (3, 2); (3, 3)]
> List.cross (*) [1;2;3] [1;2;3];;
val it : int list = [1; 2; 3; 2; 4; 6; 3; 6; 9]
Or we can implement a general cross product function:
let cross l1 l2 =
seq { for el1 in l1 do
for el2 in l2 do
yield el1, el2 };;
and use this function to get the job done:
cross [1..10] [1..10] |> Seq.map (fun (a,b) -> a*b) |> Seq.toList
To implement the same thing without for loops, you can use the solution using higher-order functions posted by Mau, or you can write the same thing explicitly using recursion:
let cross xs ys =
let rec crossAux ol2 l1 l2 =
match l1, l2 with
// All elements from the second list were processed
| x::xs, [] -> crossAux ol2 xs ol2
// Report first elements and continue looping after
// removing first element from the second list
| x::xs, y::ys -> (x, y)::(crossAux ol2 l1 ys)
// First list is empty - we're done
| [], _ -> []
crossAux ys xs ys
This may be useful if you're learning functional programming and recursion, however, the solution using sequence expressions is far more practically useful.
As a side-note, the first version by Mau can be made a bit nicer, because you can join the call to List.map with a call to List.collect id like this (you can pass the nested processing lambda directly as a parameter to collect). The cross function would look like this (Of course, you can modifiy this to take a parameter to apply to the two numbers instead of creating a tuple):
let cross xs ys =
xs |> List.collect (fun v1 ->
ys |> List.map (fun v2 -> (v1, v2)))
Incidentally, there is a free chapter from my book avaialable, which discusses how sequence expressions and List.collect functions work. It is worth noting, that for in sequence expressions directly corresponds to List.collect, so you can write the code just by using this higher order function:
let cross xs ys =
xs |> List.collect (fun v1 ->
ys |> List.collect (fun v2 -> [(v1, v2)] ))
However, see the free chapter for more information :-).

Resources