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.
Related
I found the following piece of code in the fantomas library for F#. I am having a hard time understanding this as an F# noob. From what I understand, it's a custom operator that takes 3 arguments, but why would an operator need 3 arguments? And what exactly is happening here?
/// Function composition operator
let internal (+>) (ctx: Context -> Context) (f: _ -> Context) x =
let y = ctx x
match y.WriterModel.Mode with
| ShortExpression infos when
infos
|> Seq.exists (fun x -> x.ConfirmedMultiline)
->
y
| _ -> f y
Here's an example of how fantomas uses this operator in ther CodePrinter module.
let short =
genExpr astContext e1
+> sepSpace
+> genInfixOperator "=" operatorExpr
+> sepSpace
+> genExpr astContext e2
Operators behave a lot like function names:
let (++) a b c d =
a + b + c + d
(++) 1 2 3 4
One difference is that operators can be used infix. An operator with more than 2 arguments allows infix only for the first 2 arguments:
// the following is equal:
let f = (++) 1 2 // like a function name
let f = 1 ++ 2 // with infix
f 50 60
I did not find how fantomas uses the operator you mention, would be curious, in particular since fantomas is a high profile f# project.
It might be instructive to compare this to the regular function composition operator, >>. The definition for this is:
let (>>) (f : a' -> b') (g : b' -> c') (x : a') =
g ( f x )
Esentially, it applies f to x, and then applies g to the result.
If we have the following functions:
let plusOne i = i + 1
let timesTwo j = j * 2
And apply it the following way:
let plusOneTimesTwo = plusOne >> timesTwo
What we're really doing is something like this:
let plusOneTimesTwo = (>>) plusOne timesTwo
When you don't supply all of the necessary arguments to a function (in this case, x), what you get is a function that takes the remaining arguments and then returns what the original function would return (this is partial application.) In this case, plusOneTimesTwo's function signature is now x : int -> int.
The example you've listed is essentially the same thing, but it's performing additional logic to determine whether it wants to apply the second function to the result y or to return it as-is.
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
I have asked a related question here. I want to do a similar thing but this time thread an accumulator though the array of functions. I immediately thought of Array.Reduce or Array.Fold but they are not working for me:
let AddTen x =
x + 10
let MultiplyFive x =
x * 5
let SubtractTwo x =
x - 2
let functionArray = [| AddTen; MultiplyFive; SubtractTwo |]
let calculateAnswer functionArray x = functionArray |>Array.reduce(fun acc f -> f acc)
The last line throws this exception:
Type mismatch. Expecting a
'a -> 'b but given a
'b The resulting type would be infinite when unifying ''a' and ''b -> 'a'
Am I thinking about the problem incorrectly?
Take a look at these two:
let calculateReduce = functionArray |> Array.reduce (fun f g -> f >> g)
let calculateFold x = functionArray |> Array.fold (fun acc f -> f acc) x
In the reduce version, you take an array of functions and compose them into a single function which you can later call on x.
In the fold version you fold over the array of functions, threading the accumulator through and applying each function to it in sequence. x is the initial value of the accumulator here.
Your original code didn't work, because a reduce expects a 'a -> 'a -> 'a function, which in case of an array of functions would imply composition, while you were trying to apply one function of type int -> int to another.
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.
I'm just starting up with F# and see how you can use currying to pre-load the 1st parameter to a function. But how would one do it with the 2nd, 3rd, or whatever other parameter? Would named parameters to make this easier? Are there any other functional languages that have named parameters or some other way to make currying indifferent to parameter-order?
Typically you just use a lambda:
fun x y z -> f x y 42
is a function like 'f' but with the third parameter bound to 42.
You can also use combinators (like someone mentioned Haskell's "flip" in a comment), which reorder arguments, but I sometimes find that confusing.
Note that most curried functions are written so that the argument-most-likely-to-be-partially-applied comes first.
F# has named parameters for methods (not let-bound function values), but the names apply to 'tupled' parameters. Named curried parameters do not make much sense; if I have a two-argument curried function 'f', I would expect that given
let g = f
let h x y = f x y
then 'g' or 'h' would be substitutable for 'f', but 'named' parameters make this not necessarily true. That is to say, 'named parameters' can interact poorly with other aspects of the language design, and I personally don't know of a good design offhand for 'named parameters' that interacts well with 'first class curried function values'.
OCaml, the language that F# was based on, has labeled (and optional) arguments that can be specified in any order, and you can partially apply a function based on those arguments' names. I don't believe F# has this feature.
You might try creating something like Haskell's flip function. Creating variants that jump the argument further in the argument list shouldn't be too hard.
let flip f a b = f b a
let flip2 f a b c = f b c a
let flip3 f a b c d = f b c d a
Just for completeness - and since you asked about other functional languages - this is how you would do it in OCaml, arguably the "mother" of F#:
$ ocaml
# let foo ~x ~y = x - y ;;
val foo : x:int -> y:int -> int = <fun>
# foo 5 3;;
- : int = 2
# let bar = foo ~y:3;;
val bar : x:int -> int = <fun>
# bar 5;;
- : int = 2
So in OCaml you can hardcode any named parameter you want, just by using its name (y in the example above).
Microsoft chose not to implement this feature, as you found out... In my humble opinion, it's not about "poor interaction with other aspects of the language design"... it is more likely because of the additional effort this would require (in the language implementation) and the delay it would cause in bringing the language to the world - when in fact only few people would (a) be aware of the "stepdown" from OCaml, (b) use named function arguments anyway.
I am in the minority, and do use them - but it is indeed something easily emulated in F# with a local function binding:
let foo x y = x - y
let bar x = foo x 3
bar ...
It's possible to do this without declaring anything, but I agree with Brian that a lambda or a custom function is probably a better solution.
I find that I most frequently want this for partial application of division or subtraction.
> let halve = (/) >> (|>) 2.0;;
> let halfPi = halve System.Math.PI;;
val halve : (float -> float)
val halfPi : float = 1.570796327
To generalize, we can declare a function applySecond:
> let applySecond f arg2 = f >> (|>) arg2;;
val applySecond : f:('a -> 'b -> 'c) -> arg2:'b -> ('a -> 'c)
To follow the logic, it might help to define the function thus:
> let applySecond f arg2 =
- let ff = (|>) arg2
- f >> ff;;
val applySecond : f:('a -> 'b -> 'c) -> arg2:'b -> ('a -> 'c)
Now f is a function from 'a to 'b -> 'c. This is composed with ff, a function from 'b -> 'c to 'c that results from the partial application of arg2 to the forward pipeline operator. This function applies the specific 'b value passed for arg2 to its argument. So when we compose f with ff, we get a function from 'a to 'c that uses the given value for the 'b argument, which is just what we wanted.
Compare the first example above to the following:
> let halve f = f / 2.0;;
> let halfPi = halve System.Math.PI;;
val halve : f:float -> float
val halfPi : float = 1.570796327
Also compare these:
let filterTwoDigitInts = List.filter >> (|>) [10 .. 99]
let oddTwoDigitInts = filterTwoDigitInts ((&&&) 1 >> (=) 1)
let evenTwoDigitInts = filterTwoDigitInts ((&&&) 1 >> (=) 0)
let filterTwoDigitInts f = List.filter f [10 .. 99]
let oddTwoDigitInts = filterTwoDigitInts (fun i -> i &&& 1 = 1)
let evenTwoDigitInts = filterTwoDigitInts (fun i -> i &&& 1 = 0)
Alternatively, compare:
let someFloats = [0.0 .. 10.0]
let theFloatsDividedByFour1 = someFloats |> List.map ((/) >> (|>) 4.0)
let theFloatsDividedByFour2 = someFloats |> List.map (fun f -> f / 4.0)
The lambda versions seem to be easier to read.
In Python, you can use functools.partial, or a lambda. Python has named arguments.
functools.partial can be used to specify the first positional arguments as well as any named argument.
from functools import partial
def foo(a, b, bar=None):
...
f = partial(foo, bar='wzzz') # f(1, 2) ~ foo(1, 2, bar='wzzz')
f2 = partial(foo, 3) # f2(5) ~ foo(3, 5)
f3 = lambda a: foo(a, 7) # f3(9) ~ foo(9, 7)