Create Multi-Parameter Pipeable Function F# - f#

I want to generalize my standard deviation function to allow for calculations of multiples of deviations, but still use it in the context of piping. It appears that I am setting up my function incorrectly.
let variance (x:seq<float>) =
let mean = x |> Seq.average
x |> Seq.map(fun x -> (x - mean) ** 2.0)
|> Seq.average
let stdDeviation (deviations:float, x:seq<float>) =
sqrt (x |> variance) * deviations
Example usage would be
let sTester = seq{1.0 .. 20.0}
let stdDev = sTester |> stdDeviation 1.0
I keep getting the error: The expression was expecting to have the type: seq -> a' but here has type float
Help is greatly appreciated.
Thanks,
~David

If you change your stdDeviation so that it takes two parameters, rather than a tuple then it works:
let stdDeviation (deviations:float) (x:seq<float>) =
sqrt (x |> variance) * deviations
let stdDev = sTester |> stdDeviation 1.0
The idea is that when you write let stdDeviation (deviations, x:seq<float>) then you are defining a function that takes a single parameter that is actually a tuple.
The way the |> operator works is that it supplies one parameter to the function on the right. So if you have just one parameter (which is a tuple), then the pipe isn't all that useful.
But if you say let stdDeviation deviations (x:seq<float>) then you are defining a function with two parameters. When you write input |> stdDeviations 1.0 you are then providing the first parameter on the right hand side and the input (second parameter) on the left via the pipe.

Related

kriging approximation with ILNumerics F#

I need to estimate a multivariate function, known from discrete scattered data.
I am using ILNumerics interpolation toolbox for that.
I have the following code to test the library from F#:
let inline (!) (x :RetArray<'T>) = Array<'T>.op_Implicit(x)
let inline (!!) (x:Array<'T> ) = InArray<'T>.op_Implicit(x)
let inline (!!!) (x:float[]) :InArray<float> = x
|> InArray.op_Implicit
let inline (!~) (x:float[]) : Array<float> = x
|> Array.op_Implicit
let X3 :OutArray<float>= null
let V (x:'T[]) :Array<'T> = (ILMath.vector<'T> x) |> Array.op_Implicit
let X1':Array<float> = (linspace<float>((!!!)[|-3.0|],(!!!) [|3.0|],(!!!)[|20.0|]))
|> (Seq.toArray >> V )
let Y:Array<float> = sin(X1')|> (Seq.toArray >> V)
let result = kriging( (!!)Y, (!!) X1', (!!) X1', null, X3) |> (Seq.toArray >> V)
I get the following error:
System.ArgumentException: V must be a non-empty matrix of size [k x n], where n = X.S[1]
I suspect that the internal code tries to evaluate X.S[1] and it fails, in F#, since it would need X.S.[1]; I may be completely wrong, but I would like to know whether the library may also be used from F# or it is pointless even to try.
I have also tried using the KrigingInterpolator class and I get a similar error.
On a side note: do you know any reliable library which performs multivariate interpolation for scattered data, with F#?

Does F# support multiple dispatch / multi methods?

I checked the F# example and it looks like that
// define the square function
let square x = x * x
// define the sumOfSquares function
let sumOfSquares n =
[1..n] |> List.map square |> List.sum
// try it
sumOfSquares 100
From that usage it seems like F# does not support multiple dispatch, otherwise it would be written as
...
let sumOfSquares n =
[1..n] |> map square |> sum
...
So, does it support multiple dispatch or not or has some limited support?
F# does support overload resolution on methods, for functions it's a bit more complicated as there is no direct support but you could achieve it by creating inline functions that call overloaded methods, which will result in a trait call.
You can find out how it works here.
And a good example of this is found in the FSharpPlus library, with it you can write your code as it is:
In your example:
open FSharpPlus
// define the square function
let square x = x * x
// define the sumOfSquares function
let sumOfSquares n =
[1..n] |> map square |> sum
// try it
sumOfSquares 100
// also with arrays !
let sumOfSquares2 n =
[|1..n|] |> map square |> sum
sumOfSquares2 100
Now, what if you want to sum floats? It won't work unless you make your square function inline:
// define the square function
let inline square x = x * x
// with floats
let sumOfSquares3 n =
[1.0 .. n] |> map square |> sum
// try it
sumOfSquares3 100.0
// val it : float = 338350.0
F# does not support multiple dispatch in the way you would like to use it. For methods on classes, it does support overload resolution, which is similar. In your example, List.map and List.sum are functions on the List module and therefore are not eligible for overload resolution since F# functions cannot be overloaded.

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

Currying and multiple integrals

I am interested in learning an elegant way to use currying in a functional programming language to numerically evaluate multiple integrals. My language of choice is F#.
If I want to integrate f(x,y,z)=8xyz on the region [0,1]x[0,1]x[0,1] I start by writing down a triple integral of the differential form 8xyz dx dy dz. In some sense, this is a function of three ordered arguments: a (float -> float -> float -> float).
I take the first integral and the problem reduces to the double integral of 4xy dx dy on [0,1]x[0,1]. Conceptually, we have curried the function to become a (float -> float -> float).
After the second integral I am left to take the integral of 2x dx, a (float -> float), on the unit interval.
After three integrals I am left with the result, the number 1.0.
Ignoring optimizations of the numeric integration, how could I succinctly execute this? I would like to write something like:
let diffForm = (fun x y z -> 8 * x * y * z)
let result =
diffForm
|> Integrate 0.0 1.0
|> Integrate 0.0 1.0
|> Integrate 0.0 1.0
Is this doable, if perhaps impractical? I like the idea of how closely this would capture what is going on mathematically.
I like the idea of how closely this would capture what is going on mathematically.
I'm afraid your premise is false: The pipe operator threads a value through a chain of functions and is closely related to function composition. Integrating over an n-dimensional domain however is analogous to n nested loops, i.e. in your case something like
for x in x_grid_nodes do
for y in y_grid_nodes do
for z in z_grid_nodes do
integral <- integral + ... // details depend on integration scheme
You cannot easily map that to a chain of three independet calls to some Integrate function and thus the composition integrate x1 x2 >> integrate y1 y2 >> integrate z1 z2 is actually not what you do when you integrate f. That is why Tomas' solution—if I understood it correctly (and I am not sure about that...)—essentially evaluates your function on an implicitly defined 3D grid and passes that to the integration function. I suspect that is as close as you can get to your original question.
You did not ask for it, but if you do want to evaluate a n-dimensional integral in practice, look into Monte Carlo integration, which avoids another problem commonly known as the "curse of dimensionality", i.e. that fact that the number of required sample points grows exponentially with n with classic integration schemes.
Update
You can implement iterated integration, but not with a single integrate function, because the type of the function to be integrated is different for each step of the integration (i.e. each step turns an n-ary function to an (n - 1)-ary one):
let f = fun x y z -> 8.0 * x * y * z
// numerically integrate f on [x1, x2]
let trapRule f x1 x2 = (x2 - x1) * (f x1 + f x2) / 2.0
// uniform step size for simplicity
let h = 0.1
// integrate an unary function f on a given discrete grid
let integrate grid f =
let mutable integral = 0.0
for x1, x2 in Seq.zip grid (Seq.skip 1 grid) do
integral <- integral + trapRule f x1 x2
integral
// integrate a 3-ary function f with respect to its last argument
let integrate3 lower upper f =
let grid = seq { lower .. h .. upper }
fun x y -> integrate grid (f x y)
// integrate a 2-ary function f with respect to its last argument
let integrate2 lower upper f =
let grid = seq { lower .. h .. upper }
fun x -> integrate grid (f x)
// integrate an unary function f on [lower, upper]
let integrate1 lower upper f =
integrate (seq { lower .. h .. upper }) f
With your example function f
f |> integrate3 0.0 1.0 |> integrate2 0.0 1.0 |> integrate1 0.0 1.0
yields 1.0.
I'm not entirely sure how you would implement this in a normal way, so this might not fully solve the problem, but here are some ideas.
To do the numerical integration, you'll (I think?) need to call the original function diffForm at various points as specified by the Integrate calls in the pipeline - but you actually need to call it at a product of the ranges - so if I wanted to call it only at the borders, I would still need to call it 2x2x2 times to cover all possible combinations (diffForm 0 0 0, diffForm 0 0 1, diffForm 0 1 0 etc.) and then do some calcualtion on the 8 results you get.
The following sample (at least) shows how to write similar code that calls the specified function with all combinations of the argument values that you specify.
The idea is to use continuations which can be called multiple times (and so when we get a function, we can call it repeatedly at multiple different points).
// Our original function
let diffForm x y z = 8.0 * x * y * z
// At the first step, we just pass the function to a continuation 'k' (once)
let diffFormK k = k diffForm
// This function takes a function that returns function via a continuation
// (like diffFormK) and it fixes the first argument of the function
// to 'lo' and 'hi' and calls its own continuation with both options
let range lo hi func k =
// When called for the first time, 'f' will be your 'diffForm'
// and here we call it twice with 'lo' and 'hi' and pass the
// two results (float -> float -> float) to the next in the pipeline
func (fun f -> k (f lo))
func (fun f -> k (f hi))
// At the end, we end up with a function that takes a continuation
// and it calls the continuation with all combinations of results
// (This is where you need to do something tricky to aggregate the results :-))
let integrate result =
result (printfn "%f")
// Now, we pass our function to 'range' for every argument and
// then pass the result to 'integrate' which just prints all results
let result =
diffFormK
|> range 0.0 1.0
|> range 0.0 1.0
|> range 0.0 1.0
|> integrate
This might be pretty confusing (because continuations take a lot of time to get used to), but perhaps you (or someone else here?) can find a way to turn this first attempt into a real numerical integration :-)

F# Units of measure, problems with genericity

(I'm still banging on with units of measure in F#)
I'm having a problem making 'generic' functions which take 'typed' floats.
The following mockup class is intended to keep tabs on a cumulative error in position, based on a factor 'c'. The compiler doesn't like me saying 0.<'a> in the body of the type ("Unexpected type parameter in unit-of-measure literal").
///Corrects cumulative error in position based on s and c
type Corrector(s_init:float<'a>) =
let deltaS ds c = sin (ds / c) //incremental error function
//mutable values
let mutable nominal_s = s_init
let mutable error_s = 0.<'a> //<-- COMPILER NO LIKE
///Set new start pos and reset error to zero
member sc.Reset(s) =
nominal_s <- s
error_s <- 0.<'a> //<-- COMPILER NO LIKE
///Pass in new pos and c to corrector, returns corrected s and current error
member sc.Next(s:float<'a>, c:float<'a>) =
let ds = s - nominal_s //distance since last request
nominal_s <- s //update nominal s
error_s <- error_s + (deltaS ds c) //calculate cumulative error
(nominal_s + error_s, error_s) //pass back tuple
Another related question, I believe, still to do with 'generic' functions.
In the following code, what I am trying to do is make a function which will take a #seq of any type of floats and apply it to a function which only accepts 'vanilla' floats. The third line gives a 'Value Restriction' error, and I can't see any way out. (Removing the # solves the problem, but I'd like to avoid having to write the same thing for lists, seqs, arrays etc.)
[<Measure>] type km //define a unit of measure
let someFloatFn x = x + 1.2 //this is a function which takes 'vanilla' floats
let MapSeqToNonUnitFunction (x:#seq<float<'a>>) = Seq.map (float >> someFloatFn) x
let testList = [ 1 .. 4 ] |> List.map float |> List.map ((*) 1.0<km>)
MapSeqToNonUnitFunction testList
You can change the first 'compiler no like' to
let mutable error_s : float<'a> = 0.0<_>
and the compiler seems to like that.
As for the second question, I am not seeing the same error as you, and this
[<Measure>] type km
//define a unit of measure
let someFloatFn x = x + 1.2 //this is a function which takes 'vanilla' floats
let MapSeqToNonUnitFunction (x:seq<float<_>>) = Seq.map (float >> someFloatFn) x
let testList = [ 1 .. 4 ] |> List.map float |> List.map ((*) 1.0<km>)
let testList2 = testList :> seq<_>
let result = MapSeqToNonUnitFunction testList2
printfn "%A" result
compiles for me (though the upcast to seq<_> is a little annoying, I am not sure if there is an easy way to get rid of it or not).
Aside, I think convention is to name units parameters 'u, 'v, ... rather than 'a, 'b, ...
Units of measure cannot be used as type parameters. This is because the are erased by the compiler during compilation. This question is quite similar:
F# Units of measure - 'lifting' values to float<something>

Resources