F# Scala apply method - f#

I've seen there is a method one could use in a Scala type called apply. This would enable to call on a instance of the type as if it were a function or alike. Like for example the Scala list, one could write myList(0) for the first element in the list.
Is there anything like this in F#?

F# function application is based around the FSharpFunc type internally. For example, (int -> int) is represented as FSharpFunc<int, int>.
However the F# compiler seems to somehow know the difference between a real F# function and a manual attempt to implement one, at least when the implementation language is F#.
However, I was able to fake an F# function by defining it in C#:
public class Foo : FSharpFunc<int, int>
{
public override int Invoke(int n)
{
return n + 1;
}
}
and then from F#:
> let x = Foo() :> int -> int
val x : (int -> int)
> x 3;;
val it : int = 4
I couldn't work the same trick when defining Foo in F#, even when I define it in a separate compilation unit.
The F# compiler seems to insert an attribute CompilationMapping(SourceConstructFlags.ObjectType) onto its own objects and I can't find a way to turn it off, but my C# works even if I put that attribute on manually.

Related

Does using currying result in lower performance in F#?

When writing a function that can accept currying, you can write it as a single-argument function that returns a function. For example,
let add x =
let inner y = x + y
inner
So you can either do:
add 3 4
or:
let add3 = add 3
add3 4
My question, is because you return a function, you are conceptually calling a function twice (the outer function and the inner function). Is this slower than:
let add x y = x + y
or does the compiler optimise invocations of add 3 4 in the curried definition?
let f x = fun y -> x + y
let g x y = x + y
Looking at these function definitions in dnSpy for an optimized build reveals them to be:
public static int f(int x, int y)
{
return x + y;
}
public static int g(int x, int y)
{
return x + y;
}
This is not that strange because g is actually a short-hand definition for f which is the general case. In F#-like languages function conceptually always take a single value returning a single value. Values might be functions. This is easier to see if one paranthese the function signature for f and g
val f: int -> int -> int
// Actually is
// val f: int -> (int -> int)
// ie f is a function that takes a single int and returns a function that takes a single int and returns an int.
In order to get F# to execute faster on .NET the physical representation of f in an assembly is:
public static int f(int x, int y)
While this is a more natural representation of the F# function.
public static Func<int, int> f(int x)
Would perform poorly though.
Usually F# is clever enough to avoid the overhead of the abstraction by optimization like above and on invocation. However, there are situations where F# can't optimize for you.
Imagine that you are implementing fold
let rec fold f s vs =
match vs with
| v::vs -> fold f (f s v) vs
| [] -> s
Here F# can't fully optimize f s v. The reason is that f might have a more complex implementation than above that might return a different function depending on s.
If you look in dnSpy you note that F# are invoking function using InvokeFast but this does an internal test to see if it can be invoked fast. In fold we then do this test for each value even though this is the same function.
This is the reason one might sometimes see fold written like this:
let fold f s vs =
let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt f
let rec loop s vs =
match vs with
| v::vs -> loop (f.Invoke (s, v)) vs
| [] -> s
loop s vs
Adapt here tests before the loop if f can indeed be optimized and then returns an efficient adapter. In the general case it might still be a bit slower but then this is what the caller intended.
Note; this potential performance degradation doesn't happen for simple function values like 'T -> 'U. This can always be invoked efficiently.
Hope this helps.
I tested this in LINQPad 5.
When compiler optimizations are turned off, the F# compiler will produce different IL for each snippet. In other words, if there are any optimizations going on, it's left up to the JITter, and it may very well be slower to call the first form.
However, when compiler optimizations are turned on, both forms produce identical IL outputs in every scenario I could think of to test it. In fact, with both forms, calling:
add 3 4
yields the IL equivalent of a hard-coded 7, with the entire function call optimized away:
ldc.i4.7
In other words, the F# compiler is pretty thorough when it comes to optimizing logically identical code blocks.
This is not an exhaustive answer, of course, and there could be some case where they are actually treated differently by the compiler.

What is the best way to pass generic function that resolves to multiple types

For the background: It's a variation on functional DI. Following Scott's post I wrote an interpreter. The twist is that my interpreter is generic and parametrized based on what you feed to it.
For testing purposes I'd like to pass another interpreter in, and therein lies the rub - how can I? Here's the simplified outline of the problem:
let y f =
let a = f 1
let b = f 2L
(a,b)
f is my generic interpreter, but here it is obviously constrained by the first use to int -> 'a.
In this simplified scenario I could just pass the interpreter twice, but in my actual implementation the type space is rather large (base type x3 output types).
Is there some F# mechanism that would let me do that, w/o too much overhead?
You can't do this in F# with functions. Functions lose genericity when passed as values.
However, F# does have a mechanism for doing it anyway, albeit a bit awkwardly: interfaces. Interface methods can be generic, so you can use them to wrap your generic functions:
type Wrapper =
abstract member f<'a> : 'a -> 'a
let y (w: Wrapper) =
let a = w.f 1
let b = w.f 2L
(a, b)
let genericFn x = x
// Calling y:
y { new Wrapper with member __.f x = genericFn x }
The downside is, you can't go back to higher-order functions, lest you lose genericity. You have to have interfaces all the way down to the turtles. For example, you can't simplify the instance creation by abstracting it as a function:
let mkWrapper f =
// no can do: `f` will be constrained to a non-generic type at this point
{ new Wrapper with member __.f x = f x }
But you can provide some convenience on the other side. At least get rid of type annotations:
type Wrapper = abstract member f<'a> (x: 'a): 'a
let callF (w: Wrapper) x = w.f x
let y w =
let a = callF w 1
let b = callF w 2L
(a,b)
(NOTE: there may be minor syntactic mistakes in the above code, as I'm writing on my phone)
Not sure if you're still interested, since you already accepted an answer, but as #Fyodorsoikin requested it, here's the 'static' way, it all happens at compile time, so no runtime overhead:
let inline y f =
let a = f $ 1
let b = f $ 2L
(a, b)
type Double = Double with static member inline ($) (Double, x) = x + x
type Triple = Triple with static member inline ($) (Triple, x) = x + x + x
type ToList = ToList with static member ($) (ToList, x) = [x]
let res1 = y Double
let res2 = y Triple
let res3 = y ToList
I use this technique when I need a generic function over arbitrary structures, I use to name the types with a single method 'Invokable'.
UPDATE
To add parameters to the function you add it to the DU, like this:
type Print<'a> = Print of 'a with
static member inline ($) (Print printer, x) = printer (string x)
let stdout (x:string) = System.Console.WriteLine x
let stderr (x:string) = System.Console.Error.WriteLine x
let res4 = y (Print stdout)
let res5 = y (Print stderr)
This is just a quick and simple sample code but this approach can be refined: you can use a method name instead of an operator, you can avoid having to repeat the DU in the declaration, and you can compose Invokables. If you are interested in these enhancements, let me know. I used a refinement of this approach before in production code and never had any issue.
Please look at Crates.
Here is a quick snippet describing the crux of what you want to accomplish. I believe this snippet is valuable in it helps teach us how we can formally reason about using F# and other ML type systems, by using mathematical language. In other words, it not only shows you how, it teaches you the deep principle of why it works.
The issue here is that we have reached a fundamental limitation of what is directly expressible in F#. It follows that the trick to simulating universal quantification is, therefore, to avoid ever passing the function around directly, instead hiding the type parameter away such that it cannot be fixed to one particular value by the caller, but how might one do that?
Recall that F# provides access to the .NET object system. What if we made our own class (in the object-oriented sense) and put a generic method on that? We could create instances of that which we could pass around, and hence carry our function with it (in the form of said method)?
// Encoding the function signature...
// val id<'a> : 'a -> 'a
// ...in terms of an interface with a single generic method
type UniversalId = abstract member Eval<'a> : 'a -> 'a
Now we can create an implementation which we can pass around without the type parameter being fixed:
// Here's the boilerplate I warned you about.
// We're implementing the "UniversalId" interface
// by providing the only reasonable implementation.
// Note how 'a isn't visible in the type of id -
// now it can't be locked down against our will!
let id : UniversalId =
{ new UniversalId with
member __.Eval<'a> (x : 'a) : 'a = x
}
Now we have a way to simulate a universally quantified function. We can pass id around as a value, and at any point we pick a type 'a to pass to it just as we would any value-level argument.
EXISTENTIAL QUANTIFICATION
There exists a type x, such that…
An existential is a value whose type is unknown statically, either because we have intentionally hidden something that was known, or because the type really is chosen at runtime, e.g. due to reflection. At runtime we can, however, inspect the existential to find the type and value inside.
If we don’t know the concrete type inside an existentially quantified type, how can we safely perform operations on it? Well, we can apply any function which itself can handle a value of any type – i.e. we can apply a universally quantified function!
In other words, existentials can be described in terms of the universals which can be used to operate upon them.
This technique is so useful that it is used in datatype generic programming library TypeShape, which allows you to scrap your boilerplate .NET reflection code, as well as MBrace and FsPickler for "packing existential data types". See Erik Tsarpalis' slides on TypeShape for more on "encoding safe existential unpacking in .NET" and encoding rank-2 types in .NET.
A reflection helper library like TypeShape also intuitively should cover most if not all your use cases: dependency injection needs to implement service location under the hood, and so TypeShape can be thought of as the "primitive combinator library" for building dependencies to inject. See the slides starting with Arbitrary Type Shapes: In particular, note the Code Lens data type:
type Lens<'T,'F> =
{
Get : 'T -> 'F
Set : 'T -> 'F -> 'T
}
Finally, for more ideas, you may care to read Don Stewart's PhD dissertation, Dynamic Extension of Typed Functional Languages.
We present a solution to the problem of dynamic extension in statically
typed functional languages with type erasure. The presented solution retains
the benefits of static checking, including type safety, aggressive optimizations, and native code compilation of components, while allowing
extensibility of programs at runtime.
Our approach is based on a framework for dynamic extension in a statically
typed setting, combining dynamic linking, runtime type checking,
first class modules and code hot swapping. We show that this framework
is sufficient to allow a broad class of dynamic extension capabilities in any
statically typed functional language with type erasure semantics.
Uniquely, we employ the full compile-time type system to perform runtime
type checking of dynamic components, and emphasize the use of native
code extension to ensure that the performance benefits of static typing
are retained in a dynamic environment. We also develop the concept of
fully dynamic software architectures, where the static core is minimal and
all code is hot swappable. Benefits of the approach include hot swappable
code and sophisticated application extension via embedded domain specific
languages.
Here are some coarse-grained design patterns Don lays out for future engineers to follow:
Section 3.6.3: Specializing Simulators Approach.
Demonstrates how to apply program specialization techniques to Monte-Carlo simulation of polymer chemistry. This approach demonstrates how you can "inject" specialized code to address so-called "peephole optimizations".
and a general chart to help frame the "tower of extensibility":
You could do that with a full fledged type:
type Function() =
member x.DoF<'a> (v:'a) = v
let y (f: Function) =
let a = f.DoF 1
let b = f.DoF 2L
(a,b)
y (Function())
I don't know a way to make it work with first class functions in F#

η-expansion in a pure functional language

In OCaml, it is legal to have in .mli:
val f : 'a -> 'a
val g : 'a -> 'a
and .ml:
let f x = x
let g = f
Yet in F#, this is rejected:
eta_expand.ml(2,5): error FS0034: Module 'Eta_expand' contains
val g : ('a -> 'a)
but its signature specifies
val g : 'a -> 'a
The arities in the signature and implementation differ. The signature specifies that 'g' is function definition or lambda expression accepting at least 1 argument(s), but the implementation is a computed function value. To declare that a computed function value is a permitted implementation simply parenthesize its type in the signature, e.g.
val g: int -> (int -> int)
instead of
val g: int -> int -> int.
One workaround is to η-expand the definition of g:
let g x = f x
If my code is purely functional (no exceptions, no side effects, etc.) this should be equivalent (actually, it might be even better with respect to polymorphism, depending on how the language generalizes types : in OCaml partial applications do not produce polymorphic functions, but their η-expansion does).
Is there any drawback to systematic η-expansion?
Two answers elude the question on η-expansion :-) and instead suggest that I add parentheses around my functional type. This is because, apparently, F# distinguishes at the typing level between "true" definition of functions (as λ-expressions and computed definitions, as in partial applications); presumably this is because λ-expressions directly map to CLR functions while computed definitions map to delegate objects. (I'm not sure of this interpretation and would appreciate if somebody very familiar with F# could point to reference documents describing this.)
A solution would be to systematically add parentheses to all the function types in .mli, but I fear this could lead to inefficiencies. Another would be to detect the computed functions and add parenthesize the corresponding types in the .mli. A third solution would be to η-expand the obvious cases, and parenthesize the others.
I'm not familiar enough with F# / CLR internals to measure which ones incur significant performance or interfacing penalties.
In theory, the F# function type 'a -> 'b -> 'c is the same type as 'a -> ('b -> 'c). That is, multiple argument functions are represented using the curried form in F#. You can use one where the other is expected in most cases e.g. when calling a higher-order function.
However, for practical reasons, F# compiler actually distinguishes between the types - the motivation is that they are represented differently in the compiled .NET code. This has impact on performance and also interoperability with C#, so it is useful to make that distinction.
A function Foo : int -> int -> int is going to be compiled as a member int Foo(int, int) - the compiler does not use the curried form by default, because this is more efficient when calling Foo with both arguments (more common case) and it is better for interop. A function Bar : int -> (int -> int) will be compiled as FSharpFunc<int, int> Bar(int) - actually using the curried form (and so it is more efficient to call it with just a single parameter and it will be hard to use from C#).
This is also why F# does not treat the types as equal when it comes to signatures - signature specifies the type, but here it also specifies how is the function going to be compiled. The implementation file has to provide function of the right type, but - in this case - also of the right compiled form.
Interestingly my fsi gives a more helpful error message:
/test.fs(2,5): error FS0034: Module 'Test' contains
val g : ('a -> 'a) but its signature specifies
val g : 'a -> 'a The arities in the signature and implementation differ.
The signature specifies that 'g' is function definition or lambda expression
accepting at least 1 argument(s), but the implementation is a computed
function value. To declare that a computed function value is a permitted
implementation simply parenthesize its type in the signature, e.g.
val g: int -> (int -> int) instead of
val g: int -> int -> int.
If you add brackets to get g :('a -> 'a) all is fine

How do you pass an F# function into another F# function from C# app?

I have F# class library assembly that contains two functions:
let add a b = a + b
and
let rec aggregateList list init (op:int -> int -> int) =
match list with
|[] -> init
|head::tail ->
let rest = aggregateList tail init op
op rest head
I have a C# console application which references the F# library and is attempting to do the following:
FSharpList<int> l = new FSharpList<int>(1, new FSharpList<int>(2, FSharpList<int>.Empty));
int result = myFsLibrary.aggregateList(l, 0, myFsLibrary.add);
However, the compiler complains that [myFsLibrary.add] cannot be converted from 'method group' to FSharpFunc<int, FSharpFunc<int, int>>
Other people have provided answers, but I'll just step in to say that you shouldn't do this.
Don't expose F# lists to C#. Don't expose curried functions to C#. The impedance mismatch is visible at this boundary, so it is better to expose common framework types at cross-language assembly boundaries. See
http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/fsharp-component-design-guidelines.pdf
for more advice.
You can explicitly create a function using the FSharpFunc delegate. In C#, it is more convenient to create function that takes all arguments as a tuple, so you can do that and then convert the function to a curried type using FuncConvert. Something like:
FuncConvert.FuncFromTupled(new FSharpFunc<Tuple<int, int>, int>(args =>
arags.Item1 + args.Item2))
However, if you need to call some F# function from your C# code, it is recommended to expose a function with a C#-friendly interface. In this case, I you can use Func delegate and the first argument should be IEnumerable instead of F#-specific list type:
module List =
let AggregateListFriendly inp init (op:Func<int, int, int>) =
aggregateList (List.ofSeq inp) init (fun a b -> op.Invoke(a, b))
Then your C# appplication can just use:
List.AggregateListFriendly(Enumerable.Range(0, 10), 0, (a, b) => a + b));
The reason why is that add is exported as a normal .Net style function and has the rough signature
int add(int, int)
C#, and most .Net languages, see this as a method which takes 2 int parameters and returns a single int value. F# though doesn't see functions this way. Instead it sees add as a function takes an int and returns a function which in turn takse an int and returns an int. This view of functions makes it very easy to implement operations like currying.
In order to convert from the C# view of the world to F# you need to do a bit of magic to fold a method onto itself. I accomplish this by defining a set of F# factory and extension methods to do the magic for me. For example
[<Extension>]
type public FSharpFuncUtil =
[<Extension>]
static member ToFSharpFunc<'a,'b,'c> (func:System.Func<'a,'b,'c>) =
fun x y -> func.Invoke(x,y)
static member Create<'a,'b,'c> (func:System.Func<'a,'b,'c>) =
FSharpFuncUtil.ToFSharpFunc func
I can use this library to get the appropriate F# delegate type for the add method like so
var del = FSharpFuncUtil.Create<int, int, int>(myFsLibrary.add);

Use of `inline` in F#

The inline keyword in F# seems to me to have a somewhat different purpose than what I'm used to in e.g. C. For example, it seems to affect a function's type (what are "statically resolved type parameters"? Aren't all F# types resolved statically?)
When should I be using inline functions?
The inline keyword indicates that a function definition should be inserted inline into any code which uses it. Most of the time, this will not have any effect on the type of the function. However, in rare cases, it can lead to a function which has a more general type, since there are constraints which cannot be expressed in the compiled form of the code in .NET, but which can be enforced when the function is being inlined.
The primary case where this applies is the use of operators.
let add a b = a + b
will have a monomorphic inferred type (probably int -> int -> int, but it could be something like float -> float -> float if you have code which uses this function at that type instead). However, by marking this function inline, the F# compiler will infer a polymorphic type:
let inline add a b = a + b
// add has type ^a -> ^b -> ^c when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c)
There is no way to encode this type constraint in a first class way in compiled code on .NET. However, the F# compiler can enforce this constraint at the site where it inlines the function, so that all operator uses are resolved at compile time.
The type parameters ^a, ^b, and ^c are "statically resolved type parameters", which means that the types of the arguments must be statically known at the site where those parameters are being used. This is in contrast to normal type parameters (e.g. 'a, 'b, etc.), where the parameters mean something like "some type which will be supplied later, but which can be anything".
You should use inline when you need to define a function that must have its type (re)evaluated at the site of each usage, as opposed to a normal function, which will have its type evaluated (inferred) only at the site of first usage, and then be regarded as being statically typed with that first inferred type signature everywhere else thereafter.
In the inline case, the function definition is effectively generic/ polymorphic, whereas in the normal (none-inline) case, the function is statically (and often implicitly) typed.
So, if you use inline, the following code:
let inline add a b = a + b
[<EntryPoint>]
let main args =
let one = 1
let two = 2
let three = add one two
// here add has been compiled to take 2 ints and return an int
let dog = "dog"
let cat = "cat"
let dogcat = add dog cat
// here add has been compiled to take 2 strings and return a string
printfn "%i" three
printfn "%s" dogcat
0
will compile, build and run to produce the following output:
3
dogcat
In other words, the same add function definition has been used to produce both a function that adds two integers, and a function that concatenates two strings (in fact the underlying operator overloading on + is also achieved under the hood using inline).
Whereas this code, identical except that the add function is no longer declared inline:
let add a b = a + b
[<EntryPoint>]
let main args =
let one = 1
let two = 2
let three = add one two
// here add has been compiled to take 2 ints and return an int
let dog = "dog"
let cat = "cat"
let dogcat = add dog cat
// since add was not declared inline, it cannot be recompiled
// and so we now have a type mismatch here
printfn "%i" three
printfn "%s" dogcat
0
will NOT compile, failing with this complaint:
let dogcat = add dog cat
^^^ - This expression was expected to have type int
but instead has type string
A good example of where using inline is appropriate, is when you want to define a high order function (HOF, i.e. a function taking (other) functions as arguments), e.g. a generic function to reverse the order of the application of arguments of a function with 2 arguments, e.g.
let inline flip f x y = f y x
as is done in the answer from #pad to this question Different argument order for getting N-th element of Array, List or Seq.
When should I be using inline functions?
The most valuable application of the inline keyword in practice is inlining higher-order functions to the call site where their function arguments are also inlined in order to produce a singly fully-optimized piece of code.
For example, the inline in the following fold function makes it 5× faster:
let inline fold f a (xs: _ []) =
let mutable a = a
for i=0 to xs.Length-1 do
a <- f a xs.[i]
a
Note that this bears little resemblance to what inline does in most other languages. You can achieve a similar effect using template metaprogramming in C++ but F# can also inline between compiled assemblies because inline is conveyed via .NET metadata.
The F# component design guidelines only mention a little about this. My recommendation (that aligns well with what's said there) is:
Don't use inline
Exception: you might consider using inline when writing mathematical libraries to be consumed by other F# code and you want to write functions that are generic over different numeric data types.
There are lots of other "interesting" uses of inline and static member constraints for "duck-typing" kinds of scenarios that work a bit like C++ templates. My advice is to avoid all of that like the plague.
#kvb's answer goes into more depth about what 'static type constraints' are.

Resources