Variable length tuples in f# - f#

Is it possible to write a function to accept a tuple of variable length? I'm trying to write a method that can be called like this:
let a = sum(1,2)
let b = sum(1,2,3)
EDIT: Could it be interpreted as a function call with params? Or would the method need to be written in c#:
double sum(params object[] double) {
...
}

No - tuples are by definition not variable length, and to write a function like this you'd need something like template metaprogramming in C++ - and there isn't such a thing in F#; let inline won't help you there either.
Of course, if you take a list instead, it won't look that much different:
sum[1; 2]
sum[1; 2; 3]

#PavelMineav is right, you can't do it, but note that members can be overloaded, a la
type Foo() =
member this.sum(x,y) = x + y
member this.sum(x,y,z) = x + y + z
let foo = new Foo()
printfn "%d" (foo.sum(1,2))
printfn "%d" (foo.sum(1,2,3))
whereas let-bound functions cannot.

Related

making type aliases non interchangeable in F#

Here is an example:
type T =
TimeSpan
let x (y: T) =
printfn $"{y}"
let a:TimeSpan = TimeSpan.FromSeconds(3)
let b:T = TimeSpan.FromSeconds(3)
let a' = x a
let b' = x b
In this case, I want to make a type which is identical to TimeSpan but is NOT TimeSpan. I would like the ability to cast between one another, but not be equivalent when it comes to function signatures.
For example, the x function takes a type T, so the line:
let a' = x a
shouldn't compile because it passes a TimeSpan
but the line:
let b' = x b
is passing a type T and should compile.
Is there some simple and elegant way to achieve this? the goal for this is to be able to use TimeSpan, but constrain the options to some specific values.
Right now I'm using an enum that needs to be convert to TimeSpan and then TimeSpans get reconvert to the enum if they exist in the enum. It's rather ugly.
I want to make a type which is identical to TimeSpan but is NOT TimeSpan. I would like the ability to cast between one another, but not be equivalent when it comes to function signatures.
That's not possible in F#, but the usual way to accomplish something like it is with single-case unions, such as:
type T = T of TimeSpan
let x (T y) =
printfn "%A" y // y is the inner TimeSpan value
let a:TimeSpan = TimeSpan.FromSeconds(3.0)
let b:T = TimeSpan.FromSeconds(3.0) |> T
let a' = x a // doesn't compile
let b' = x b
The general issue I think you're dealing with here is called "primitive obsession".
You can either use a single cased DU, or you can use units of measure to do this. UMX specifically supports timespans.
https://github.com/fsprojects/FSharp.UMX

type inference on abstract type with a tuple

Based on this kvb's answer, this code compiles (F#4) and runs :
type Untupler = abstract Apply : 'u * 'u -> 'u
let myotherFun arg1 arg2 =
printfn "myotherFun result is : %A %A" arg1 arg2
let myFunction tup1 tup2 (i:Untupler) =
myotherFun (i.Apply tup1) (i.Apply tup2)
let reskvb = myFunction (1,2) ("Hello","World") { new Untupler with member __.Apply (x,y) = snd (x,y) }
But if the last line is replaced by the initial answer :
let reskvb = myFunction (1,2) ("Hello","World") { new Untupler with member __.Apply x = fst x }
then the compiler complains with error FS0768 :
The member 'Apply' does not accept the correct number of arguments, 2 arguments are expected
I do not understand why the compiler seems to fail to infer that x is indeed a tuple. Or is there another issue I am missing ? Thx.
The reason for this is that when you start using interfaces, you move into F#'s support for Object-Oriented Programming, and in F#, all OOP interop methods are tupled by default.
Thus, the Apply method is interpreted as being a method that takes two method arguments, rather than a function that takes a single tuple as input.

Type inference of functions as arguments

I would like to write a function which takes several tupples as arguments and choose theirs ith elements and passes to another function, where i is given as another argument. I've tried sth like this:
let function (tup1:'A*'A) (tup2:'B*'B) i =
otherFunction (i tup1) (i tup2)
function Tup1 Tup2 fst
I've got an error, because i was expected to be 'A*'A ->'A not 'B*'B->'B.
Is it any way to make this code to work?
Thanks in advance.
You basically want to pass an argument of type ∀'a.'a*'a->'a, but in F# (and other MLs), only rank-1 polymorphism is supported so you can't do this directly. The workaround is to define a new type with a generic method to emulate higher-rank polymorphism:
type Untupler =
abstract Apply : 'a*'a -> 'a
let myFunction tup1 tup2 (i:Untupler) =
otherFunction (i.Apply tup1) (i.Apply tup2)
myFunction Tup1 Tup2 { new Untupler with member __.Apply (x,y) = x }
When you use the function i with tup1, it's inferred to be of the type 'A * 'A -> 'A. This means that when you use it with tup2, the only way that can work is if tup2 is also an 'A * 'A.
The function i can't change type within the same function. If there's a way to do what you want, I'm not aware of it, but you can sidestep the issue like this:
let myFunction x y =
otherFunction x y
Call it like this:
myFunction (fst tup1) (fst tup2)
This puts slightly more responsibility of the caller, but the advantage is that it's possible :)

F# mutable function arguments

Is there a way to have mutable function arguments in F#, that would allow something like
let mutable i = 9
let somefun n = n <- 12; ()
somefun i
(* *not* a real-world example *)
I do understand that this can be made to work by wrapping it into a record type
type SomeRec = { mutable i: int }
let ri = { i = 9 }
let someotherfun r = r.i <- 12; ()
and that this can be done in a similar fashion for class members. However, even after browsing through the whole F# Language Specification (yes, I did!), there seems to be no syntax to allow the first case, and the compiler appears to be quite unhappy about my trying this. I was hoping there would be some sort of type annotation, but mutable cannot be used in such.
I also know that I should not be doing this sort of thing in the first place, but the first case (int binding) and the second (record type) are semantically identical, and any such objection would hold for both cases equally.
So I think that I am missing something here.
You can use ref as arguments
let v = ref 0
let mutate r =
r := 100
mutate v
printfn "%d" !v
Or byref keyword
let mutable v = 0
let mutate (r : byref<_>) =
r <- 100
mutate &v
printfn "%d" v
Use byref keyword which is equivalent to C# ref.
See Passing by reference.

F# block arguments

C# has anonymous delegates. So I can write:
public vois foo(string d, Action t){
t();
}
In ruby:
def foo d
yield
end
How to do the same in F#? Prefered syntax is:
foo "dfdfdf" { do something here }
Thanks
Your first example isn't an anonymous method -- it's just passing and calling through a delegate (which might refer to a named or an anonymous method). To do this in F#, just provide and call a function argument:
let foo n f = f n
let square n = n * n
let result = foo 123 square
printfn "%A" result
To create the equivalent of an anonymous method in F#, use the fun keyword:
let result2 = foo 123 (fun n -> n * n)
Have a look at this article about Higher Order Functions in F#. Higher Order Functions are functions which accept other functions as arguments, and sound like the concept you are describing.
open System
// create a function that expects an Action delegate and executes it
let foo (actionDelegate:Action) (s:String) = actionDelegate.Invoke();
// create a function that meets Action delegate
let ActionFunction param = Console.Write("Action in action")
// call foo passing ActionFunction
foo (new Action(ActionFunction)) "my string"

Resources