List.map with two function parameters, in F# - f#

I came across this syntax:
[10.; 11.; 12.]
|> List.map (fun a b -> a * b)
in what case does List.map have two parameters (fun a b)?
This is the output in Jupyter Lab:

That's a fun example, because it looks confusing and usually doesn't come up in practice, so it caught me off-guard initially.
In short, what happens is you're mapping a list of floats into a list of float -> float functions. It's easier to see if you rewrite it as something like this:
let results =
[10.; 11.; 12.]
|> List.map (fun a -> (fun b -> a * b))
You pass a float -> float -> float function as the mapper, and it gets partially applied to the element from the input list. The second argument b is not being applied though, so the output of the mapping is a function that takes a float and multiplies it by the partially applied element of the list, and the overall result is a list of float -> float functions.
You can then apply those functions to some value like this:
results
|> List.map (fun f -> f 2.)

Related

How to avoid changing parameter order

I am currently doing some of the excercises from exercism.io. One of the excercises is summing up all numbers in a sequence that are a multiple of one or more numbers from a different sequence. Splitting the problem into smaller functions seemed like a good idea and i came up with this:
let multipleOf m n =
n % m = 0
let anyMultipleOf (m: int list) n =
m
|> Seq.exists (multipleOf n)
let sumOfMultiples m n =
[1..n-1]
|> Seq.filter (anyMultipleOf m)
|> Seq.sum
The idea being, that i can use partial application to "bake in" the m parameter into my (any)multipleOf functions. But this code doesn't work the way i want it to, because Seq.exists (multipleOf n) actually applies n as my m parameter.
How can i refactor this code without having to reverse the parameter order of my multipleOf function?
Note: I want a solution that uses my multipleOf function inside my anyMultipleOf function. This solution works, but doesn't reuse my first function:
let anyMultipleOf (m: int list) n =
m
|> Seq.exists (fun x -> n % x = 0)
I did type in a suggestion to use flip, but the obvious thing to do is this:
let anyMultipleOf (m: int list) n =
m
|> Seq.exists (fun x -> multipleOf x n)
flip is a nice tool to have, but pipelines of flipped functions are painful to read.
While it's unclear to me why you don't redefine anyMultipleOf to take the the list as the last argument, you can always use flip:
let flip f x y = f y x
This function exists in Haskell, but not in FSharp.Core, which is the reason you'd have to define it yourself.
As an example, flip anyMultipleOf returns a function with the type int -> int list -> bool, which, if I understand the question correctly, is what you want.
You can define yourself a function which just do that :
Takes a function and 2 arguments in reversed order and return the result of applying the arguments in the right order to the function
let flip f y x = f x y

Define sum of square without defining parameter

I want to define sumOfSquares without explicity using parameter, relying instead on functional composition
Here's my code below
let sumOfSquares = Seq.map (fun n -> n * n) >> Seq.sum
However, I got the following error
stdin(80,5): error FS0030: Value restriction. The value 'sumOfSquares'
has been inferred to have generic type
val sumOfSquares : ('_a -> int) when '_a :> seq<int>
Either make the arguments to 'sumOfSquares' explicit or, if you do not intend for
it to be generic, add a type annotation.
One way to resolve it is by using parameters
let sumOfSquares nums = nums |> Seq.map (fun n -> n * n) |> Seq.sum
and this will work. However, I want to see if I can define sum of squares by using composition alone
Update
Here's a nice article describing the issue I've encountered: Value Restriction.
Make a type annotation:
let sumOfSquares : seq<int> -> int =
Seq.map (fun n -> n * n) >> Seq.sum
So lets see what happens when the type inference tries to work here. First you have
Seq.map (fun n -> n * n) >> Seq.sum
Now as Seq allows for anything that implements Seq, we can input int list int[] or many others.
As a result, you get this as the type
val sumOfSquares : ('_a -> int) when '_a :> seq<int>
Now the problem is that sumofSquares is a value (which is a function). Unfortunately, you can't have a generic value in a top level binding. You can though have a generic function, if you make the arguments explicit.
As a result, one alternative to a type annotation is to make the argument explicit like so
let sumOfSquares s= s |> Seq.map (fun n -> n * n) |> Seq.sum
And this works
Searching SO for "value restriction errors" should give some more examples of this problem.

"summing" functions in F#

I have a list of functions in F# which are all of type (float -> float -> float -> float). I want to do some kind of fold on the sequence to get a single function which returns the sum of all of the functions.
For instance, I could pass the values 1.0, 2.0, and 3.0 to every function in the list, and get a return value from each one. Then I could compute the sum of all of these values. However, I want to generalize this.
I know how to do this recursively, but I feel like it should be doable in one line. Is there a concise way to accomplish this task?
The solution by #Lee is a one liner you're looking for. If you wanted to save a few characters, you can use List.sumBy which first applies a given function to an element of the list (similar to List.map) and then sums the result (just like List.sum):
let sumAll (fs:(_ -> _ -> _ -> float) list) a b c =
List.sumBy (fun f -> f a b c) fs
Both this and Lee's version uses type annotations to specify that the functions in the list return float. This is needed, because otherwise the compiler does not know what kind of numbers you want to sum using List.sum (floats, integers, etc.). This ambiguity needs to be resolved to compile the function.
Alternatively, you could mark the function as inline and then it would be inlined when you call it (and it would work for multiple different numeric types). You can also pass the fs parameter as the last one and use partial function application:
let inline sumAll a b c = List.sumBy (fun f -> f a b c)
Now you can call it using pipelining as follows: fs |> sumAll 1 2 3.
let sumAll (fs: (float -> float -> float -> float) list) a b c = List.map (fun f -> f a b c) fs |> Seq.sum
The answers by #Lee and #Tomas are great, but there is a shorter way.
If you can afford passing (a, b, c) as a triple upon invocation:
let inline sumAll() = (|||>) >> List.sumBy
// usage
let predicates =
[
fun a b c -> a
fun a b c -> b * 42.0 - c
]
let ret1 = predicates |> sumAll()(1.0, 2.0, 3.0)
It will be also generic:
let predicates2 =
[
fun a b c -> c - 10
fun a b c -> a + c * 42
]
let ret2 = predicates2 |> sumAll()(1, 2, 3)
A more readable way which supports curried arguments:
let sumAllCurried a b c = (a,b,c) |> (|||>) |> List.sumBy<_, float>
// usage
let ret3 = predicates |> sumAllCurried 1.0 2.0 3.0
Note, I'm using a type parameter on List.sumBy since it looks shorter than typing an entire type specification for f.

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).

Type mismatch with Async in F#

I've just started messing around with F# and am trying to do some basic parallel computation to get familiar with the language. I'm having trouble with type mismatches. Here's an example:
let allVariances list =
seq {
for combination in allCombinations list do
yield (combination, abs(targetSum - List.sum combination))
}
let compareVariance tup1 tup2 =
if snd tup1 < snd tup2 then
tup1
else
tup2
let aCompareVariance tup1 tup2 =
async { return compareVariance tup1 tup2 }
let matchSum elements targetSum =
allVariances elements
|> Seq.reduce aCompareVariance
|> Async.Parallel
|> Async.RunSynchronously
So, "allVariances elements" produces a seq<float list * float>. CompareVariance takes two of those <float list * float> tuples and returns the one with the smaller second item (variance). My goal is to use Reduce to end up with the tuple with the smallest variance. However, I get a type mismatch on the aCompareVariance argument:
Error 1 Type mismatch. Expecting a float list * float -> float list * float -> float list * float but given a float list * float -> float list * float -> Async<float list * float> The type 'float list * float' does not match the type 'Async<float list * float>'
It seems like the Async return type isn't accepted by Reduce?
Seq.reduce takes a function and a sequence and reduces the list using the function. That is, the outcome of reducing a sequence {a1;a2;a3;...;an} with function f will be f(f(...f(f(a1,a2),a3),...),an))...). However, the function you're passing can't be applied this way, because the return type (Async<float list * float>) doesn't match the argument types (float list * float). What exactly are you trying to achieve?
Also, keep in mind that async computations are great for asynchronous work, but not ideal for parallel work. See F#: Asynch and Tasks and PLINQ, oh my! and Task Parallel Library vs Async Workflows.
EDIT
Here's one way to write a function which will reduce items more like you expected, operating sort of like this:
[|a1; a2; a3; a4|]
[|f a1 a2; f a3 a4|]
f (f a1 a2) (f a3 a4)
At each stage, all applications of f will take place in parallel. This uses Async.Parallel, which as mentioned above is probably less appropriate than using the Task Parallel Library (and may even be slower than just doing a normal synchronous Array.reduce). As such, just consider this to be demonstration code showing how to piece together the async functions.
let rec reduce f (arr:_[]) =
match arr.Length with
| 0 -> failwith "Can't reduce an empty array"
| 1 -> arr.[0]
| n ->
// Create an array with n/2 tasks, each of which combines neighboring entries using f
Array.init ((n+1)/2)
(fun i ->
async {
// if n is odd, leave last item alone
if n = 2*i + 1 then
return arr.[2*i]
else
return f arr.[2*i] arr.[2*i+1]})
|> Async.Parallel |> Async.RunSynchronously
|> reduce f
Note that converting items to and from Async values all happens internally to this function, so it has the same type as Array.reduce and would be used with your normal compareVariance function rather than with aCompareVariance.

Resources