This question already has answers here:
How to write a function for generic numbers?
(5 answers)
Closed 8 years ago.
I am writing an assembly with some functionality that is intended to work with numeric primitives, i.e. float, int, decimal, etc.
One of the functions takes two sequences and calculates the running average of the two. An implementation for floats may look like this
let average x y = (x+y)/2.
let a = [1..10] |> List.map float
let b = List.rev [1..10] |> List.map float
let result = (a, b) ||> List.map2 average
How can I make this generic for numeric primitives?
F# has so called "static member constraints" that can be used for writing generic numerical code. This is limited to F# (because .NET has no concept like this).
In general, you need to mark the function as inline. This will make the standard operators inside the function behave as generic. In addition, you need to avoid using constants (like 2.0). You can typically replace them with some operation from the LanguagePrimitives module. For example, your average function can be written as generic using:
let inline average x y =
LanguagePrimitives.DivideByInt (x + y) 2
For more information check out this blog post about generic numeric computations in F#.
Related
I have already done some searches, and this question is a duplicate of another post. I am posting this just for future reference.
Is it possible to define SUMPRODUCT without explicitly using variable names x, y?
Original Function:
let SUMPRODUCT x y = List.map2 (*) x y |> List.sum
SUMPRODUCT [1;4] [3;25] // Result: 103
I was hoping to do this:
// CONTAINS ERROR!
let SUMPRODUCT = (List.map2 (*)) >> List.sum
// CONTAINS ERROR!
But F# comes back with an error.
I have already found the solution on another post, but if you have any suggestions please let me know. Thank you.
Function composition only works when the input function takes a single argument. However, in your example, the result of List.map2 (*) is a function that takes two separate arguments and so it cannot be easily composed with List.sum using >>.
There are various ways to work around this if you really want, but I would not do that. I think >> is nice in a few rare cases where it fits nicely, but trying to over-use it leads to unreadable mess.
In some functional languages, the core library defines helpers for turning function with two arguments into a function that takes a tuple and vice versa.
let uncurry f (x, y) = f x y
let curry f x y = f (x, y)
You could use those two to define your sumProduct like this:
let sumProduct = curry ((uncurry (List.map2 (*))) >> List.sum)
Now it is point-free and understanding it is a fun mental challenge, but for all practical purposes, nobody will be able to understand the code and it is also longer than your original explicit version:
let sumProduct x y = List.map2 (*) x y |> List.sum
According to this post:
What am I missing: is function composition with multiple arguments possible?
Sometimes "pointed" style code is better than "pointfree" style code, and there is no good way to unify the type difference of the original function to what I hope to achieve.
This question already has answers here:
Static extension methods supporting member constraints
(2 answers)
Closed 7 years ago.
Given a list of TimeSpan values, I would like to get the average TimeSpan. It would be elegant if I could just write it like this:
let durations = [TimeSpan.FromSeconds 4.; TimeSpan.FromSeconds 2.]
let avg = durations |> List.average
However, the compiler complains about this:
The type 'TimeSpan' does not support the operator 'DivideByInt'
which is quite reasonable, since TimeSpan indeed doesn't define DivideByInt.
To work around this issue, I attempted to extend TimeSpan like this (before using List.average):
type TimeSpan with
static member DivideByInt (ts : TimeSpan) (i : int) =
(float ts.Ticks) / (float i) |> int64 |> TimeSpan.FromTicks
While this implementation seems to work correctly when used directly, it unfortunately doesn't seem to make the compiler happy when using List.average.
While I'm very much aware that I can use List.averageBy, or just write a custom function to calculate the average of a list of TimeSpan values, I thought it'd be elegant if one could write durations |> List.average.
Is there any way to enable that syntax?
No, it's not possible. See this old question. In theory it might be possible to implement it in a future version of F#.
when I tried to overload the op using
type TimeSpan with
member this.op_DivideByInt (ts : TimeSpan) (i : int) =
(float ts.Ticks) / (float i) |> int64 |> TimeSpan.FromTicks
let durations = [TimeSpan.FromSeconds 4.; TimeSpan.FromSeconds 2.]
let avg = durations |> List.average
I get the following compiler warning:
Extension members cannot provide operator overloads. Consider defining the operator as part of the type definition instead.
so it looks like we can't do this.
I played around a little with F# today, wrote this:
let sq x = x * x
let i = sq 3
let d = sq 3.0
It compiles if I remove either the third or the fourth line, but not if both are present.
I get the error This expression should have type 'int', but has type 'float'.
The type inference works so that your function sq has type int -> int, because the first time compiler sees you use that function, you pass it an integer. So it assumes that sq is a function that takes an integer, and by definition of the function (x * x) it also returns an integer.
It is a bit complicated to define a fully generic arithmetic function in F#, but one way to do it is to make the function inline, like so:
let inline sq x = x * x
This way the body of your function will be inlined each time at the call site, so using an inlined sq function will be the same as substituting it's body every time it's used.
This approach has it's drawbacks, and I think it will be interesting for you to see this question.
Let-bound functions cannot be overloaded. In your specific case, you could use inline, which inlines the function body at compile time and can therefore choose an appropriate implementation of *, e.g.
let inline sq x = x * x
The other answers are correct but they leave out an important part of the jigsaw: the fact that in F# there are no implicit conversions between, for example, ints and floats. This is the reason why your second call is in effect calling a different, non existent, overload with a float argument.
The function let sq x = x * x on default has type int -> int.
If you put it in the context of a let d = sq 3.0, F# compiler will infer its type as float -> float.
In any way, this function can have only one type signature, either int->int, or float->float.
This is a limitation in how the bindings are implemented. There are 2 alternatives.
Firstly, add inline to the declaration.
Secondly, use member bindings in a class and override the different types.
F# is an ML with OOP. What's the closest it comes to Haskell generalized algebraic data types and typeclasses?
The answer depends on what problem are you trying to solve. F# does not have typeclasses and GADTs, so there is no direct mapping. However, F# has various mechanisms that you would use to solve problems that you typically solve in Haskell using GADTs and typeclasses:
If you want to represent object structures and be able to add new concrete implementations with different behaviour, then you can often use standard OO and interfaces.
If you want to write generic numeric code, you can use static member constraints (here is an example), which is probably technically the closest mechanism to type classes.
If you want to write more advanced generic code (like universal printer or parser) then you can often use the powerful F# runtime reflection capabilities.
If you need to parameterize code by a set of functions (that perform various sub-operations required by the code) then you can pass around an implementation of an interface as #pad shows.
There is also a way to emulate Haskell type classes in F#, but this is usually not an idiomatic F# solution, because the F# programming style differs from the Haskell style in a number of ways. One fairly standard use of this is defining overloaded operators though (see this SO answer).
At the meta-level, asking what is an equivalent to a feature X in aother language often leads to a confused discussion, because X might be used to solve problems A, B, C in one language while another language may provide different features to solve the same problems (or some of the problems may not exist at all).
In F#, you often use interfaces and inheritance for these purposes.
For examples' sake, here is a simple typeclass using interfaces and object expressions:
/// Typeclass
type MathOps<'T> =
abstract member Add : 'T -> 'T -> 'T
abstract member Mul : 'T -> 'T -> 'T
/// An instance for int
let mathInt =
{ new MathOps<int> with
member __.Add x y = x + y
member __.Mul x y = x * y }
/// An instance for float
let mathFloat =
{ new MathOps<float> with
member __.Add x y = x + y
member __.Mul x y = x * y }
let XtimesYplusZ (ops: MathOps<'T>) x y z =
ops.Add (ops.Mul x y) z
printfn "%d" (XtimesYplusZ mathInt 3 4 1)
printfn "%f" (XtimesYplusZ mathFloat 3.0 4.0 1.0)
It may not look very beautiful, but it's F#-ish way to do it. For a more Haskell-like solution which uses a dictionary-of-operations, you can have a look at this nice answer.
This question already exists:
Closed 12 years ago.
Possible Duplicate:
Functional programming: currying
I'm reading the free F# Wikibook here:
http://en.wikibooks.org/wiki/F_Sharp_Programming
There's a section explaining what Partial Functions are. It says that using F# you can partially use a function, but I just can't understand what's going on. Consider the following code snippet that is used an example:
#light
open System
let addTwoNumbers x y = x + y
let add5ToNumber = addTwoNumbers 5
Console.WriteLine(add5ToNumber 6)
The ouput is 11. But I'm not following. My function 'add5ToNumber' doesn't ask for a paramter so why can I invoke it and give it it one?
I really like learning about F# these days, baby steps!
Basically, every function in F# has one parameter and returns one value. That value can be of type unit, designated by (), which is similar in concept to void in some other languages.
When you have a function that appears to have more than one parameter, F# treats it as several functions, each with one parameter, that are then "curried" to come up with the result you want. So, in your example, you have:
let addTwoNumbers x y = x + y
That is really two different functions. One takes x and creates a new function that will add the value of x to the value of the new function's parameter. The new function takes the parameter y and returns an integer result.
So, addTwoNumbers 5 6 would indeed return 11. But, addTwoNumbers 5 is also syntactically valid and would return a function that adds 5 to its parameter. That is why add5ToNumber 6 is valid.
Currying is something like this:
addTwoNumbers is a function that takes a number and returns a function that takes a number that returns a number.
So addTwoNumbers 5 is in fact a function that takes a number and returns a number, which is how currying works. Since you assign addTwoNumbers 5 to add5ToNumber, that make add5ToNumber a function that takes a number an returns a number.
I don't know what type definition looks like in F# but in Haskell, the type definition of functions makes this clear:
addTwoNumbers :: (Num a) => a -> a -> a
On the other hand, if you wrote addTwonumbers to take a two tuple,
addTwoNumbers :: (Num a) => (a, a) -> a
then is would be a function that takes a two tuple and returns a number, so add5ToNumber would not be able to be created as you have it.
Just to add to the other answers, underneath the hood a closure is returned when you curry the function.
[Serializable]
internal class addToFive#12 : FSharpFunc<int, int>
{
// Fields
[DebuggerBrowsable(DebuggerBrowsableState.Never), CompilerGenerated, DebuggerNonUserCode]
public int x;
// Methods
internal addToFive#12(int x)
{
this.x = x;
}
public override int Invoke(int y)
{
return Lexer.add(this.x, y);
}
}
This is known as eta-expansion : in a functional language,
let f a = g a
Is equivalent to
let f = g
This makes mathematical sense : if the two functions are equal for every input, then they're equal.
In your example, g is addTwoNumbers 5 and the code you wrote is entirely equivalent to:
let add5toNumber y = addTwoNumbers 5 y
There are a few situations where they are different:
In some situations, the type system may not recognize y as universally quantified if you omit it.
If addTwoNumbers 5 (with one parameter only) has a side-effect (such as printing 5 to the console) then the eta-expanded version would print 5 every time it's called while the eta-reduced version would print it when it's defined. This may also have performance consequences, if addTwoNumbers 5 involved heavy calculations that can be done only once.
Eta-reduction is not very friendly to labels and optional arguments (but they don't exist in F#, so that's fine).
And, of course, unless your new function name is extremely readable, providing the names of the omitted arguments is always a great help for the reader.
addTwoNumbers accepts 2 arguments (x and y).
add5ToNumber is assigned to the output of calling addTwoNumbers with only 1 argument, which results in another function that "saves" the first argument (x -> 5) and accepts one other argument (y).
When you pass 6 into add5ToNumber, its passing the saved x (5) and the given y (6) into addTwoNumbers, resulting in 11