I have a discriminated union (tagged value) which is supposed to represent the degree of a polynomial
type Degree =
|MinusInf
|Fin of int
So I have a function which gives me the degree of a polynomial
>deg [1;2;3;4];;
val it : Degree = Fin 3
Now, my question is, how can I make a function which allows me to add degrees so that:
Fin 2 + Fin 3 = Fin 5
All best
There's a fairly detailed article on MSDN. In short, you want to define a function like this on your Degree type:
type Degree =
|MinusInf
|Fin of int
static member (+) (a: Degree, b: Degree) : Degree =
match a, b with
| Fin x, Fin y -> Fin (x+y)
| _, _ -> MinusInf
let x = Fin 2 + Fin 3
Related
RE: What is the best way to pass generic function that resolves to multiple types
Please read the referenced link before going further below
I am trying to extend the concept and pass a generic function that takes 2 parameters and does something with them.
The static approach works, however the interface based one causes a compile error (see the code lines marked with //error):
The declared type parameter '?' cannot be used here since the type parameter cannot be resolved at compile time.
Does anyone know how to fix it?
module MyModule
type T = Content of int
with
static member (+) ((Content i1), (Content i2)) = Content (i1 + i2)
static member (*) ((Content i1), (Content i2)) = Content (i1 * i2)
type W = { Content: int }
with
static member (+) ({Content = i1}, {Content = i2}) = { Content = i1 + i2 }
static member (*) ({Content = i1}, {Content = i2}) = { Content = i1 * i2 }
type Sum = Sum with static member inline ($) (Sum, (x, y)) = x + y
type Mul = Mul with static member inline ($) (Mul, (x, y)) = x * y
let inline f1 (la: 'a list) (lb: 'b list) reducer =
let a = la |> List.reduce (fun x y -> reducer $ (x, y))
let b = lb |> List.reduce (fun x y -> reducer $ (x, y))
(a, b)
type I = abstract member Reduce<'a> : 'a -> 'a -> 'a
let f2 (la: 'a list) (lb: 'b list) (reducer: I) =
let a = la |> List.reduce reducer.Reduce
let b = lb |> List.reduce reducer.Reduce
(a, b)
let main ()=
let lt = [Content 2; Content 4]
let lw = [{ Content = 2 }; { Content = 4 }]
let _ = f1 lt lw Sum
let _ = f1 lt lw Mul
let _ = f2 lt lw { new I with member __.Reduce x y = x + y} //error
let _ = f2 lt lw { new I with member __.Reduce x y = x * y} //error
0
The problem with your attempt is that you can't use operators + or * on parameters x and y, because it's not known that their type 'a has those operators defined.
To answer your further question in comments about how to achieve it anyway - if you want to use multiplication and addition on any type 'a that the caller chooses, you have to specify that. For an interface method, the only way to do this is by constraining the type parameter 'a, and the only two kinds of constraints that .NET runtime supports are "has a parameterless constructor" and "implements a given interface or inherits from a given class".
The latter one would be useful in your case: make both types implement the interface and then constrain type parameter 'a to implement that interface:
type IArithmetic<'a> =
abstract member add : 'a -> 'a
abstract member mult : 'a -> 'a
type T = Content of int
with
interface IArithmetic<T> with
member this.add (Content y) = let (Content x) = this in Content (x + y)
member this.mult (Content y) = let (Content x) = this in Content (x * y)
type W = { Content: int }
with
interface IArithmetic<W> with
member this.add y = { Content = this.Content + y.Content }
member this.mult y = { Content = this.Content * y.Content }
type I = abstract member Reduce<'a when 'a :> IArithmetic<'a>> : 'a -> 'a -> 'a
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
// the constraint right here
...
let _ = f2 lt lw { new I with member __.Reduce x y = x.add y }
let _ = f2 lt lw { new I with member __.Reduce x y = x.mult y }
Is this a bit awkward? I guess so, but you're kind of doing the same thing for the SRTP version, so why not?
The core idea is: if you want your Reduce method to work not with just any type, but only with types that can do certain things, you have to specify what those things are. In the SRTP case you're doing that by defining the (+) and (*) operators. In the interface case you're doing that by implementing the interface.
Q: But can I make the interface somehow pick up the (+) and (*) operators?
A: In general, no. The .NET runtime just doesn't support the kind of constraints like "any type that has a method with certain signature". This means that such constraints can't be compiled down to IL, which means they can't be used in an interface implementation.
And this is the price you pay for using SRTPs: all those inline functions - they don't get compiled to IL, they always get expanded (inserted, substituted) at use sites. For small, simple functions, this is no big deal. But if your whole program is like that, you might see some unexpected compiled code bloat, potentially translating to slower startup time etc.
Having said all that, I must note that the code you're showing is toy POC kind of code, not intended to solve any real, practical problem. And as such, most musings on it are in danger of being completely useless.
If you have an actual problem in mind, perhaps try sharing it, and somebody would suggest the best solution for that specific case.
In particular, I have a nagging feeling that you might not actually need higher-rank functions (that's what it's called when a function doesn't lose genericity when passed as parameter).
I am currently porting some code from Java to F# that deals with multidimensional functions. It supports variable dimension, so in the original implementation each point is represented as an array of doubles. The critical function of the code is an optimisation routine, that basically generates a sequence of points based on some criteria, evaluates a given function at these points and looks for a maximum. This works for any dimension. The operations I need are:
check the dimension of a point
create a new point with the same dimension of a given point
set (in procedural or functional sense) a given coordinate of a point
In F# I could obviously also use arrays in the same way. I was wandering though if there is a better way. If the dimension was fixed in advance, the obvious choice would be to use tuples. Is it possible to use tuples in this dynamic setting though?
No, tuples will be fixed by dimension. Also note that .NET tuples are boxed. If you are operating on large collections of points with small dimension (such as arrays of 2d points), using structs may help.
If you really want to push the F#/.NET advantage over Java, have a look at generics. Writing code with generics allows to write code that works for any dimension, and use different representations for different dimensions (say structs for 1-3 dimensions, and vectors for larger dimensions):
let op<'T where 'T :> IVector> (x: 'T) =
...
This is only relevant though if you are willing to go a long way to get the absolutely best performance and generality. Most projects do not need that, stick with the simplest thing that works.
For the fun of it, here is an extended example of how to utilize generics and F# inlining:
open System.Numerics
type IVector<'T,'V> =
abstract member Item : int -> 'T with get
abstract member Length : int
abstract member Update : int * 'T -> 'V
let lift<'T,'V when 'V :> IVector<'T,'V>> f (v: 'V) : 'V =
if v.Length = 0 then v else
let mutable r = v.Update(0, f v.[0])
for i in 1 .. v.Length - 1 do
r <- r.Update(i, f v.[i])
r
let inline norm (v: IVector<_,_>) =
let sq i =
let x = v.[i]
x * x
Seq.sum (Seq.init v.Length sq)
let inline normalize (v: 'V) : 'V =
let n = norm v
lift (fun x -> x / n) v
[<Struct>]
type Vector2D<'T>(x: 'T, y: 'T) =
member this.X = x
member this.Y = y
interface IVector<'T,Vector2D<'T>> with
member this.Item
with get (i: int) =
match i with
| 0 -> x
| _ -> y
member this.Length = 2
member this.Update(i: int, v: 'T) =
match i with
| 0 -> Vector2D(v, y)
| _ -> Vector2D(x, v)
override this.ToString() =
System.String.Format("{0}, {1}", x, y)
[<Sealed>]
type Vector<'T>(x: 'T []) =
interface IVector<'T,Vector<'T>> with
member this.Item with get (i: int) = x.[i]
member this.Length = x.Length
member this.Update(i: int, v: 'T) =
let a = Array.copy x
a.[i] <- v
Vector(a)
override this.ToString() =
x
|> Seq.map (fun e -> e.ToString())
|> String.concat ", "
[<Struct>]
type C(c: Complex) =
member this.Complex = c
static member Zero = C(Complex(0., 0.))
static member ( + ) (a: C, b: C) = C(a.Complex + b.Complex)
static member ( * ) (a: C, b: C) = C(a.Complex * b.Complex)
static member ( / ) (a: C, b: C) = C(a.Complex / b.Complex)
override this.ToString() = string c
let v1 = Vector2D(10., 30.)
normalize v1
|> printfn "%O"
let v2 = Vector2D(C(Complex(1.25, 0.8)), C(Complex(0.5, -1.)))
normalize v2
|> printfn "%O"
let v3 = Vector([| 10.; 30.; 50.|])
normalize v3
|> printfn "%O"
Note that norm and normalize are fairly general, they cope with specialized 2D vectors and generalized N-dimensional vectors, and with different component types such as complex numbers (you can define your own). The use of generics and F# inlining ensure that while general, these algorithms perform well for the special cases, using compact representations. This is where F# and .NET generics shine compared to Java, where you are obliged to create specialized copies of your code to get decent performance.
this simple function:
let sum a b = a + b
will work only for int types
how to make it so that it would also work for float and long ?
Use inline:
let inline sum a b = a + b
UPDATE:
If you're interested in writing your own polymorphic numerical functions, you should use both inline and LanguagePrimitives module.
Here is a polymorphic cosine function from the thread Converting Haskell Polymorphic Cosine function to F#:
let inline cosine n (x: ^a) =
let one: ^a = LanguagePrimitives.GenericOne
Seq.initInfinite(fun i -> LanguagePrimitives.DivideByInt (- x*x) ((2*i+1)*(2*i+2)))
|> Seq.scan (*) one
|> Seq.take n
|> Seq.sum
The example function you give only works for int types because of type inference; the type inference mechanism will automatically infer int because it sees the addition. If you want to make the same function for float and long, you'd either do inline as Pad has said or you could do this:
let sumFloat (a:float) b = a + b
let sumLong (a:int64) b = a + b
But inline is the right mechanism to get the generic "any type that supports addition" behavior that you're looking for.
let f g x y = g x y
f (+) 0.0 1.0;;
f (=) 0 1;;
I like this solution as well.
I am currently experimenting with F#. The articles found on the internet are helpful, but as a C# programmer, I sometimes run into situations where I thought my solution would help, but it did not or just partially helped.
So my lack of knowledge of F# (and most likely, how the compiler works) is probably the reason why I am totally flabbergasted sometimes.
For example, I wrote a C# program to determine perfect numbers. It uses the known form of Euclids proof, that a perfect number can be formed from a Mersenne Prime 2p−1(2p−1) (where 2p-1 is a prime, and p is denoted as the power of).
Since the help of F# states that '**' can be used to calculate a power, but uses floating points, I tried to create a simple function with a bitshift operator (<<<) (note that I've edit this code for pointing out the need):
let PowBitShift (y:int32) = 1 <<< y;;
However, when running a test, and looking for performance improvements, I also tried a form which I remember from using Miranda (a functional programming language also), which uses recursion and a pattern matcher to calculate the power. The main benefit is that I can use the variable y as a 64-bit Integer, which is not possible with the standard bitshift operator.
let rec Pow (x : int64) (y : int64) =
match y with
| 0L -> 1L
| y -> x * Pow x (y - 1L);;
It turns out that this function is actually faster, but I cannot (yet) understand the reason why. Perhaps it is a less intellectual question, but I am still curious.
The seconds question then would be, that when calculating perfect numbers, you run into the fact that the int64 cannot display the big numbers crossing after finding the 9th perfectnumber (which is formed from the power of 31). I am trying to find out if you can use the BigInteger object (or bigint type) then, but here my knowledge of F# is blocking me a bit. Is it possible to create a powerfunction which accepts both arguments to be bigints?
I currently have this:
let rec PowBigInt (x : bigint) (y : bigint) =
match y with
| bigint.Zero -> 1I
| y -> x * Pow x (y - 1I);;
But it throws an error that bigint.Zero is not defined. So I am doing something wrong there as well. 0I is not accepted as a replacement, since it gives this error:
Non-primitive numeric literal constants cannot be used in pattern matches because they
can be mapped to multiple different types through the use of a NumericLiteral module.
Consider using replacing with a variable, and use 'when <variable> = <constant>' at the
end of the match clause.
But a pattern matcher cannot use a 'when' statement. Is there another solution to do this?
Thanks in advance, and please forgive my long post. I am only trying to express my 'challenges' as clear as I can.
I failed to understand why you need y to be an int64 or a bigint. According to this link, the biggest known Mersenne number is the one with p = 43112609, where p is indeed inside the range of int.
Having y as an integer, you can use the standard operator pown : ^T -> int -> ^T instead because:
let Pow (x : int64) y = pown x y
let PowBigInt (x: bigint) y = pown x y
Regarding your question of pattern matching bigint, the error message indicates quite clearly that you can use pattern matching via when guards:
let rec PowBigInt x y =
match y with
| _ when y = 0I -> 1I
| _ -> x * PowBigInt x (y - 1I)
I think the easiest way to define PowBigInt is to use if instead of pattern matching:
let rec PowBigInt (x : bigint) (y : bigint) =
if y = 0I then 1I
else x * PowBigInt x (y - 1I)
The problem is that bigint.Zero is a static property that returns the value, but patterns can only contain (constant) literals or F# active patterns. They can't directly contain property (or other) calls. However, you can write additional constraints in where clause if you still prefer match:
let rec PowBigInt (x : bigint) (y : bigint) =
match y with
| y when y = bigint.Zero -> 1I
| y -> x * PowBigInt x (y - 1I)
As a side-note, you can probably make the function more efficent using tail-recursion (the idea is that if a function makes recursive call as the last thing, then it can be compiled more efficiently):
let PowBigInt (x : bigint) (y : bigint) =
// Recursive helper function that stores the result calculated so far
// in 'acc' and recursively loops until 'y = 0I'
let rec PowBigIntHelper (y : bigint) (acc : bigint) =
if y = 0I then acc
else PowBigIntHelper (y - 1I) (x * acc)
// Start with the given value of 'y' and '1I' as the result so far
PowBigIntHelper y 1I
Regarding the PowBitShift function - I'm not sure why it is slower, but it definitely doesn't do what you need. Using bit shifting to implement power only works when the base is 2.
You don't need to create the Pow function.
The (**) operator has an overload for bigint -> int -> bigint.
Only the second parameter should be an integer, but I don't think that's a problem for your case.
Just try
bigint 10 ** 32 ;;
val it : System.Numerics.BigInteger =
100000000000000000000000000000000 {IsEven = true;
IsOne = false;
IsPowerOfTwo = false;
IsZero = false;
Sign = 1;}
Another option is to inline your function so it works with all numeric types (that support the required operators: (*), (-), get_One, and get_Zero).
let rec inline PowBigInt (x:^a) (y:^a) : ^a =
let zero = LanguagePrimitives.GenericZero
let one = LanguagePrimitives.GenericOne
if y = zero then one
else x * PowBigInt x (y - one)
let x = PowBigInt 10 32 //int
let y = PowBigInt 10I 32I //bigint
let z = PowBigInt 10.0 32.0 //float
I'd probably recommend making it tail-recursive, as Tomas suggested.
I'd like to compose functions in a certain way. Please consider these 2 functions in pseudocode (not F#)
F1 = x + y
F2 = F1 * 10 // note I did not specify arguments for F1, 'reverse curry' for lack of a better word
What I would like for F# to do is figure out that since
let F1 x y = x + y
//val F1 : int -> int -> int
the code let F2 = F1 * 10 would give me the same signature as F1: val F2 : int -> int -> int, and calling F2 2 3 would result in 50: (2 + 3) * 10. That would be rather clever...
What happens is quite different tho. The first line goes as expected:
let F1 x y = x + y
//val F1 : int -> int -> int
but when I add a second line let F2 = F1 * 10 it throws off F#. It complains that the type int does not match the type 'a -> 'b -> 'c and that F1 now requires member ( + ).
I could of course spell it out like this:
let F1(x, y) = x + y
let F2(x, y) = F1(x, y) * 10
But now I might as well have used C#, we're not that far away anymore. The tupled arguments break a lot of the elegance of F#. Also my real functions F1 and F2 have a lot more arguments than just 2, so this makes me go cross eyed, exactly what I wanted to dodge by using F#. Saying it like this would be much more natural:
let F1 x y = x + y
let F2 = F1 * 10
Is there any way I can (almost) do that?
For extra credits: what exactly goes on with these error messages? Why does the second line let F2 = F1 * 10 change the typing on the first?
Thanks in advance for your thoughts,
Gert-Jan
update
Two apporaches that (almost) do what's described.
One using a tuple. Second line looks a little quirky a first, works fine. Small drawback is I can't use currying now or I'll have to add even more quirky code.
let F1 (a, b) = a + b
let F2 = F1 >> (*) 10
F2(2, 3) // returns 50
Another approach is using a record. That is a little more straight forward and easier to get at first glance, but requieres more code and ceremony. Does remove some of the elegance of F#, looks more like C#.
type Arg (a, b) =
member this.A = a
member this.B = b
let F1 (a:Arg) = a.A + a.B
let F2 (a:Arg) = F1(a) * 10
F2 (Arg(2, 3)) // returns 50
There is no pattern for this in general. Using combinators (like curry and uncurry) as suggested by larsmans is one option, but I think the result is less readable and longer than the explicit version.
If you use this particular pattern often, you could define an operator for multiplying a function (with two parameters) by a scalar:
let ( ** ) f x = fun a b -> (f a b) * x
let F1 x y = x + y
let F2 = F1 ** 10
Unfortunately, you cannot add implementation of standard numeric operators (*, etc.) to existing types (such as 'a -> 'b -> int). However, this is quite frequent request (and it would be useful for other things). Alternatively, you could wrap the function into some object that provides overloaded numeric operators (and contains some Invoke method for running the function).
I think an appropriate name for this would be lifting - you're lifting the * operator (working on integers) to a version that works on functions returning integers. It is similar to lifting that is done in the C# compiler when you use * to work with nullable types.
To explain the error message - It complains about the expression F1 * 10:
error FS0001: The type 'int' does not match the type ''a -> 'b -> 'c'
I think it means that the compiler is trying to find an instantiation for the * operator. From the right-hand side, it figures out that this should be int, so it thinks that the left-hand side should also be int - but it is actually a function of two arguments - something like 'a -> 'b -> c'.
That would be rather clever...
So clever that it would beat the hell out of the type system. What you want is array programming as in APL.
Is there any way I can (almost) do that?
I don't speak F#, but in Haskell, you'd uncurry F1, then compose with *10, then curry:
f2 = curry ((*10) . uncurry f1)
Which in an ML dialect such as F# becomes something like:
let curry f x y = f (x,y)
let uncurry f (x,y) = f x y
let mult x y = x * y
let F1 x y = x + y
let F2 = curry (uncurry F1 >> mult 10)
(I wasn't sure if curry and uncurry are in the F# standard library, so I defined them. There may also be a prettier way of doing partial application of * without defining mult.)
BTW, using point-free (or rather pointless in this case) approach one could define these functions in the following way:
let F1 = (+)
let F2 = (<<)((*)10) << F1