Alternatives to functors in F# - f#

I would like to write the following:
module A =
type Token
let foo Token =
module B =
type Token
let foo Token =
let run (m : module) =
m.B
|> m.foo
basically a function that's generic in the module. Is there a way to do this in F#?

As kvb pointed out in a comment, it is hard to give an answer without a realistic example, because the best approach will depend on what you're actually trying to do.
In this trivial example, I would probably use F# interface to represent Token and add Foo as a member. Assuming that Foo returns an int, you can write the definition like this:
type Token =
abstract Foo : unit -> int
Then you can implement different tokens either using classes (which is quite heavyweight) or using object expressions. For example:
let tok = { new Token with
member x.Foo () = 42 }
The code that corresponds to your run function is just a call of the Foo member: tok.Foo()

Related

Passing arguments by reference in curried arguments

I'm attempting to implement the interface IDispatchMessageInspector (of WCF fame) in F#:
open System.ServiceModel.Dispatcher
open System.ServiceModel.Channels
type ServiceInterceptor() as interceptor =
abstract member PreInvoke : byref<Message> -> obj
abstract member PostInvoke : byref<Message> -> obj -> unit
default x.PreInvoke m = null
default x.PostInvoke m s = ()
interface IDispatchMessageInspector with
member x.AfterReceiveRequest(request, channel, instanceContext) = interceptor.PreInvoke(&request)
member x.BeforeSendReply(reply : byref<Message>, correlationState) = interceptor.PostInvoke &reply correlationState
This fails to compile with the following error:
However, if I modify my code to the following (note the change of signature in PostInvoke) everything works:
open System.ServiceModel.Dispatcher
open System.ServiceModel.Channels
type ServiceInterceptor() as interceptor =
abstract member PreInvoke : byref<Message> -> obj
abstract member PostInvoke : byref<Message> * obj -> unit
default x.PreInvoke m = null
default x.PostInvoke (m, s) = ()
interface IDispatchMessageInspector with
member x.AfterReceiveRequest(request, channel, instanceContext) = interceptor.PreInvoke(&request)
member x.BeforeSendReply(reply : byref<Message>, correlationState) = interceptor.PostInvoke(&reply, correlationState)
Is this behaviour expected? And if so could someone explain the reasoning behind it....
The reason is that byref<'T> is not a real type in .NET. F# uses this for representing values that are passed via ref and out parameters, but it is not a normal type that could appear anywhere in your program.
F# restricts the scope in which they can be used - you can only use them for local variables (basically passing around a reference or a pointer) and you can use them as method parameters (where the compiler can then compile it as a method parameter).
With curried methods, the compiler is producing a property that returns a function value and so (under the cover), you get something like a property PostInvoke of type FSharpFunc<T1, FSharpFunc<T2, T3>>. And here, T1 or T2 cannot be byref<T> types, because byref is not a real .NET type. So that's why curried methods cannot have byref parameters.
Another case where you can see this is if you, for example, try to create a list of byref values:
let foo () =
let a : list<byref<int>> = []
a
Here you get:
error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.

How to expose the type as friendly as possible to both C# and F#?

For example, if I have written a module in F#
module Lib
type A =
member this.x1 x = ...
let helpa x = ...
let helpb x = ...
type B =
member this.y1 x = ...
let helpc x = ...
typeA with
member this.x2 x = ...
typeB with
member this.y2 x = ...
It works well in F# by open Lib, However, if I want to consume it in C# (where I am only interested in types and member functions in Lib), each time I create a type I have to new Lib.A(...). It becomes rather annoying there is no way to omit the module names. Calling a static method like Lib.A.C() is even more of a hassle.
Then I try to replace module with namespace, each time I introduce some helper functions I have to create a new module with a new name. Occasionally I can manage to rearrange all helper functions into 1 module, but that would result in less readable code somehow.
What would be a better structure for this?
Wish I had: Using * = Lib.* for C#.
F# offers more flexibility than C# here, so I would expose it to C# in the standard way, i.e., enclose types in a namespace. Something like this, I think, offers the best of both worlds:
namespace Lib
type A =
member this.x1 x = ()
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module A =
let helpa x = ()
let helpb x = ()
type B =
member this.y1 x = ()
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module B =
let helpb x = ()
type A with
member this.x2 x = ()
type B with
member this.y2 x = ()
The F# collections follow a similar design. You can use the [<AutoOpen>] and [<RequireQualifiedAccess>] attributes to further control how the modules are used from F#.
I think you already mentioned the best option in your answer - define the file with namespace declaration at the top (this way, you can write just using Lib in C#) and then place all helper functions in modules.
Helper functions that are clearly associated with some type (e.g. with A) could be placed into a module named A (similarly to F# functions in the List module that are associated with the List<'T> type).
This is a bit more work, because you need to mark the module with a special attribute (to avoid name clash), but it will be easy to use from both F# and C# (and I think having nice use is more important than saving a few keystrokes when building the library):
namespace Lib
// Declaration of the 'A' type and helper functions in 'A' module
type A() =
member this.x1 x = 10
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module A =
let helpa (x:A) = x.x1
let helpb (x:A) = x.x1
// Declaration of the 'B' type and helper functions in 'B' module
type B() =
member this.y1 x = 10
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module B =
let helpc (x:B) = x.y1
// Member augmentations for easy use from C#
type A with
member this.x2 x = A.helpa this
type B with
member this.y2 x = B.helpc this

How to get a reference to a function that doesn't take parameters in F#?

I sometimes have the need to get the function itself, not the value, of a zero-parameter function in F#, for instance for memoization. I.e., I have this:
let memoize (f: 'a -> 'b) =
let dict = new Dictionary<'a, 'b>()
let memoizedFunc (input: 'a) =
match dict.TryGetValue(input) with
| true, x -> x
| false, _ ->
let answer = f input
dict.Add(input, answer)
answer
memoizedFunc
and this works perfectly, but now I have the following function:
let private getDataSlowOperation =
// implementation
and when I try to memoize that, it gives a type mismatch (essentially the mismatch between the return type of getDataSlowOperation and the 'a type). I can solve this by changing the function as follows:
let private getDataSlowOperation bogus =
// implementation
Now this works, but it seems odd to have to change the function signature to get memoization to work:
let memoGetDataSlowOperation = memoize getDataSlowOperation
I've experimented with inline fun declarations, but this creates, of course, a new anonymous function and the memoization doesn't work with that. Any ideas how to resolve this? Any keyword / operator I've forgotten about?
What you defined is not a function, it's just a value.
In order to define it as a function you can write this:
let private getDataSlowOperation() =
// implementation
UPDATE
To summarize the discussion:
This is the right way to write it as a function, however the code would still not work but that's a different problem.
The code would fail at runtime because () is compiled to null and by using a Dictionary you can't use null for the Key. You can use a Map instead.
John pointed out that memoization for functions without parameters makes no sense, I agree.
Still, if you use a Dictionary for functions with parameters you will run into the same problem with values that are compiled to null, ie: None

why is the implementation of my abstract member not public

I've been struggling to get this to compile for about an hour. It must be something stupid. Can you spot it?
in my lib project:
namespace TravelerStuff
open System
type Traveler =
abstract GetData : unit -> unit
type public DeltaTraveler() =
interface Traveler with
member v.GetData () =
printf "hello"
and in my console test app:
[<EntryPoint>] let main _ =
let traveler = new TravelerStuff.DeltaTraveler()
traveler.GetData // this line won't compile: (The field, constructor or member 'GetData' is not defined)
As gradbot says, F# doesn't currently implicitly convert values to interfaces when searching for members. Also, F# only uses explicit interface implementation (as known from C#) and not implicit implementation where members are not only compiled as implementation of an interface, but also as ordinary (directly visible) members of the type.
Aside from casting, you can duplicate the member in the type definition:
type DeltaTraveler() =
member v.GetData () = printf "hello"
interface Traveler with
member v.GetData () = v.GetData()
Also, if you just want to implement an interface, but don't need to add any members, you can use F# object expressions (which are more lightweight):
let deltaTraveler() =
{ new Traveler with
member v.GetData () = printf "hello" }
// The function directly returns value of type 'Traveler'
let t = deltaTraveler()
t.GetData()
You need to upcast. F# currently won't do it for you in this situation.
(traveler :> TravelerStuff.Traveler).GetData()
// open the namespace to reduce typing.
open TravelerStuff
(traveler :> Traveler).GetData()
Snip from F# docs.
In many object-oriented languages,
upcasting is implicit; in F#, the
rules are slightly different.
Upcasting is applied automatically
when you pass arguments to methods on
an object type. However, for let-bound
functions in a module, upcasting is
not automatic, unless the parameter
type is declared as a flexible type.
For more information, see Flexible Types (F#).

Formatting fluent/method chaining code from C# in F#

Some apis like Ninject use fluent style apis, example:
Bind<ISomething>()
.To<Something>()
.WithConstructorArgument("arg1", "somevalue")
.OnActivation(x => x.DoSomething())
When I try format the code like this in F# the compiler complains at the whitespace between method calls.
Is it possible to put the method calls on seperate lines? I was thinking something like the pipelining operator |> but not exactly sure how in this case.
How should this be formatted in F#?
Are you sure this doesn't work?
Bind<ISomething>()
.To<Something>()
.WithConstructorArgument("arg1", "somevalue")
.OnActivation(fun x -> x.DoSomething())
(note one space before the .s)
Yeah, it's fine:
type ISomething = interface end
type Something = class end
type Foo() =
member this.To<'a>() = this //'
member this.WithConstructorArgument(s1,s2) = this
member this.OnActivation(x:Foo->unit) = this
member this.DoSomething() = ()
let Bind<'a>() = new Foo() //'
let r =
Bind<ISomething>()
.To<Something>()
.WithConstructorArgument("arg1", "somevalue")
.OnActivation(fun x -> x.DoSomething())
So long as you have some leading whitespace when you try to continue a single expression onto multiple lines, you're ok.
(Note that pipelining in general won't work unless you have APIs designed for it with curried method parameters.)

Resources