Is it possible to implement friend function and friend class (as in c++) in F#?
Update:
Since there is no friend function/class in f#, and friend is not even a reserved keyword for future expansion, I'm wondering is there any problems with the friend mechanism in F# that make the developers to decide not to implement it?
(such as in "protected" access modifier).
Suggestion 1: Brian, signature file -
I don't think that this thing work properly. If you have a closure (e.g. lambda expression in A, which is a different object than the instance of A) that evaluate B.X , it's won't work
Suggestion 2: Massif (+Mitya0), InternalsVisibleTo -
It's not clear to me, Are you writing this in the second class or it expose the class to the entire assembly?
Note that you can use signature files to mimic friend.
If you want A to be a friend of B, so A can access internals of B that others cannot see, you can do e.g.
// File1.fs
type B() =
let x = 42 // private field
member this.X = x // public getter
type A() =
member this.PeekInto(b : B) =
b.X
but also have
// File1.fsi
type B =
new : unit -> B
// do not expose X in the signature
type A =
new : unit -> A
PeekInto : B -> int
and now A's implementation can see B.X but the sequel of the program cannot see B.X.
Signature files are pretty awesome for creating arbitrary encapsulation boundaries.
As mitya has pointed out. Just use the InternalsVisibleTo attribute on the class you want to see the protected members of, or on the entire assembly. (I do this all the time for unit testing purposes).
[<assembly:System.Runtime.CompilerServices.InternalsVisibleTo("UnitTestModule")>]
Works a treat.
The concept of friends as it exists in C++ doesn't exactly translate to F#, but you can use the internal accessibility modifier to allow access to all classes in the same .NET assembly. This is probably what you are looking for.
From what I see of documentation, there is a friend notion in C#, but the same documentation suggests F# doesn't have this ability.
Related
Given the type
type T =
static member OverloadedMethod(p:int) = ()
static member OverloadedMethod(p:string) = ()
Let's suppose we want to create a generic function that resolves to the specific overload based on the type of the parameter. The most intuitive way would be
//Case 1
let inline call o = T.OverloadedMethod o //error
call 3
call "3"
but this, despite the inline definition, doesn't work and the compiler complains
Error FS0041 A unique overload for method 'OverloadedMethod' could not
be determined based on type information prior to this program point. A
type annotation may be needed. Candidates: static member
T.OverloadedMethod : p:int -> unit, static member T.OverloadedMethod :
p:string -> unit
We can achieve what we want though, for example using the "operator trick"
//Case 2
type T2 =
static member ($) (_:T2, p:int) = T.OverloadedMethod(p)
static member ($) (_:T2, p:string) = T.OverloadedMethod(p)
let inline call2 o = Unchecked.defaultof<T2> $ o
call2 3
call2 "3"
The F# compiler here does (apparently) some more work and doesn't simply fall back to the .NET resolution.
Yet, this looks ugly and implies code duplication. It sounds like Case 1 should be possible.
What technical reasons justify this behaviour? My guess is that there is some trade-off (perhaps with .NET interoperability), but couldn't find more information.
EDIT
From the posts I extract this as a reason:
"a trait call is an F# compiler feature, so there must be two different ways of writing a simple call and a trait call. Using the same syntax for both is not convenient because it might be confusing, some uses could arise where a simple call is compiled as a trait call accidentally".
Let's put the question in a different perspective:
Looking at the code, it really seems straightforward what the compiler should do:
1) call is an inline function, so defer compilation to the use site
2) call 3 is an use site, where the parameter is of type int. But T.OverloadedMethod(int) exists, so let's generate a call to it
3) call "3" like previous case with string in place of int
4) call 3.0 error as T.OverloadedMethod(float) doesn't exist
I would really like to see a code example where letting the compiler do this would be a problem that justifies requiring the developer to write the additional code for the trait call.
At the end of the day, isn't one of F# strengths "conciseness and intuitiveness"?
Here we are in presence of a case where it looks like it could be better.
The trade-offs stem from the fact that this it's a completely erased compiler trick. This means that:
C# code can't see (and take advantage of) any call2 function, it can only see your two $ method overloads.
All information about call2 is gone at runtime, meaning you couldn't invoke it through reflection, for example.
It won't show up in call stacks. This may be a good or a bad thing -- for example, in recent versions of the F# compiler, they've selectively inlined certain functions to make async stacktraces a bit nicer.
The F# is baked in at the call site. If your calling code in is assembly A call2 comes from assembly B, you can't just replace assembly B with a new version of call2; you have to recompile A against the new assembly. This could potentially be a backwards compatibility concern.
A rather interesting benefit is that it can lead to drastic performance improvements in specialized cases: Why is this F# code so slow?. On the flip side, I'm sure there are circumstances where it could cause active harm, or just bloat the resulting IL code.
The reason of that behavior is that T.OverloadedMethod o in
let inline call o = T.OverloadedMethod o
is not a trait call. It's rather simple .NET overloading that must be solved at the call site, but since your function type doesn't imply which overload to solve it simply fails to compile, this functionality is desired.
If you want to "defer" the overload resolution you need to do a trait call, making the function inline is necessary but not sufficient:
let inline call (x:'U) : unit =
let inline call (_: ^T, x: ^I) = ((^T or ^I) : (static member OverloadedMethod: _ -> _) x)
call (Unchecked.defaultof<T>, x)
Using an operator saves you many keystrokes by inferring automatically these constraints but as you can see in your question, it requires to include a dummy parameter in the overloads.
I've been programming in F# for some years and there's an "issue" that's been bothering me for some time and I have not been able to solve. It is not a bug, I think it is a design decision, but anyway, the problem is this: is there a way to delay (maybe that's not the correct word for this) the implementation of interfaces?, that is, not implementing them in the initial definition, but later, maybe in the same file after I have implemented a module for the type. I'll explain with a simplified example:
Suppose I have the following data structure:
type 'T MyCollection =
(*type definition*)
interface IEnumerable<'T> with
member this.GetEnumerator () =
(* I don't want to implement it here
because I still don't have the module
with a toSeq function *)
If I implemented the method right there, I would have to also implement all the functions as methods of the type and then the module would be just a "proxy" for calling the methods. This way I'm creating a OO-first data structure and then creating a module (overloaded with type annotations) to allow for a functional-first usage. I would prefer to write a functional-first data structure (cleaner since the type inference can work better) and then create a OO wrapper to allow a better intellisense support for languages like C#. That approach complies with what the design guidelines for F# tells us, but the interfaces can't be implemented anywhere but in the initial definition of the type. That restriction forces me to write the whole data structure with members.
I've been looking for examples and I've found that the list implementation in FSharp.Core list does exactly what I want, but I can't do that, the compiler won't let me.
I'm almost sure that this is a design decision, maybe to avoid encouraging bad practices, I don't know, but I don't consider my wish to be a bad practice. Also I'm well aware of the linear nature of the fsharp compiler.
Please if any of you know how to do what I want, I'll be glad if you tell me. Also, if any of you know why I should not follow this approach I'll be glad to know too. There must be a reason why this is not a problem for anyone else.
Thanks in advance.
I completely agree that this is unfortunate problem. The trick that is used in the source code of 'a list in the F# Core library is to define the implementation of the interface in a type augmentation. The compiler does not complain when you add members to a type in this way, but it says that adding implementation of an interface in this way is deprecated. However, it does not prevent you from doing this. The following compiles fine for me:
open System.Collections
open System.Collections.Generic
type MyCollection<'T> =
{ Data : 'T list }
interface IEnumerable<'T>
interface IEnumerable
let getEnumerator { Data = d } =
(d :> seq<_>).GetEnumerator()
type MyCollection<'T> with
interface IEnumerable<'T> with
member this.GetEnumerator() = getEnumerator this
interface IEnumerable with
member this.GetEnumerator() = (getEnumerator this) :> _
The fact that this is deprecated is a bit unfortunate. I quite like this style and I use it when it makes sense. You can start a discussion about this on F# user voice and perhaps it could be turned back into a normal accepted feature :-)
type Tag(Kids) =
member this.Kids = Kids
static member (-) (this: Tag, that: list<obj>) =
Tag(that::this.Kids)
The point of this code is to construct a new object based on an existing one, but modifying one (or more) fields on the object. Basically, it is a proxy for a thing.setX(...) mutator method, except using immutable data.
It looks incredibly ugly and verbose, and I'm sure there must be a better way of doing it while maintaining the immutability of the data, but I haven't figured out how. Is there some syntactically nice way of doing this?
EDIT: Just for clarity, I also have other classes in the hierarchy:
type HTMLTag(s, Classes, Kids, Styles) =
inherit Tag(Kids)
member this.NominalTag = s
member this.Classes = Classes
member this.Styles: list<String * String> = Styles
static member (-) (this: HTMLTag, that: list<obj>) =
HTMLTag(this.NominalTag, this.Classes, that::this.Kids, this.Styles)
Apart from it being very verbose, the - function's "copy with modification" thing is completely non-generic: even though I am doing the same thing each time (copy w/ modification to same variable) I have to rewrite the whole thing all over again, which isn't very nice.
One thing I find very annoying is that this would be very simple with mutation:
static member (-) (this: Tag, that: list<obj>) =
this.Kids = that :: this.Kids
this
But I'm trying to keep everything immutable as far as possible
Copy and update record expressions[MSDN] are meant to handle this exact case. If you can use a record type instead you can do
type Tag =
{ NominalTag : obj
Classes : obj
Kids : list<obj>
Styles : list<String * String> }
static member (-) (this: Tag, that: list<obj>) =
{ this with Kids = this.Kids # that }
The compiled forms of this code and yours are virtually identical.
Incidentally, it's odd that the (-) operator is being used to append...but I presume this is a contrived case.
UPDATE
Now that you've updated your question I'm confused about what you want to do. If you want to return a new object I don't see how mutation helps you.
A more functional approach (vs inheritance) is to separate your data and behaviors, the data being records and the behaviors functions grouped within a module. If you want behavior to be shared across types, use interfaces. Records can implement interfaces.
I have a question about the best way to go about the following
I Have a class B, I have a combinator on B,
let foo : B -> int.
I want the class B to have the combinator encapsulated as a method, so I add it with a type extension.
I then later on realize that foo is quite expensive and want to cache it's result with lazy evaluation
So I add a huge clutch to the system by passing the combinator as a function to the constructor and then initializing a field with foo = lazy(foo self) in the constructor.
i.e.
type foo =
class
val x : int Lazy
new (comb) as self = {x=lazy(comb self);}
end
let something (x:foo) = 1
type foo with
new() = foo(something)
this obviously feels wrong
the two options I see for fixing this are 1, make an interface and have foo inherit that interface, 2, make everything a static method and then make combinators out of those static methods(sort of the opposite of attaching them to classes...)
Neither of these are hugely appealing and I was wondering if I missed option 3
Oh, and I haven't been able to get let rec and to work quite right with this, nor would i really want to as "something" in the above statement depends on a function that depends on a function that depends on a function(3 deep).
any advice would be appreciated
I don't think there is anything wrong with your current design. The key point is that if you define the type Foo as well as the extension to the type in a same file (and the same module), then F# will combine the two parts of the definition into a single .NET type. So, the fact that it is defined in two separate parts is just an implementation detail.
If you don't want to expose the constructor that takes the combinator, you can mark it as private. Together with a few additional changes (i.e. use implicit constructor syntax), the snippet would look like this:
type Foo private (comb) as self =
let x : Lazy<int> = lazy comb self
let something (x:Foo) = 1
type Foo with
new() = Foo(something)
If you want to keep something as a separate function, then this is a fine solution. Many numeric types in the F# PowerPack follow this pattern (see for example definition of complex numbers)
I don't quite grok what you're after, but I think this may help:
type foo(comb) as self =
let x = lazy(comb self)
static member something (x:foo) = 1
new() = foo(foo.something)
A type can be recursive with its own static member, so this is a simpler way to write your code.
I know I must be missing something really obvious here. B.GetInstance().Call() generates the error: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.
I'm using v1.9.9.9.
type A() =
member x.Call() = B.GetInstance().Call()
and B() =
static member GetInstance() = new B()
member x.Call() = ()
I just discovered that this works: (B.GetInstance() :> B).Call()
Any idea why the cast is necessary?
Frequently when you've got a recursive set of methods whose types to infer, F# needs help. A more pleasant alternative would be to annotate the definition of B.GetInstance:
type A() =
member x.Call() = B.GetInstance().Call()
and B() =
static member GetInstance() : B = new B()
member x.Call() = ()
I believe that the reason you run into this problem is that F# tries to solve all inferred types on all methods in A and B simultaneously (because they are defined as mutually recursive types), and this leads to problems, but perhaps someone from the F# team will weigh in.
The quick summary is that in a recursive group (e.g. members in one type, or members of recursive types like we have here) F# reads the declarations in left-to-right top-to-bottom order, followed by the definitions in left-to-right top-to-bottom order. So in this instance when it reaches the definition of A.Call, it has not yet read the definition of B.GetInstance and therefore does not (yet!) know that the return type of GetInstance will be B.
Keith's answer nails it for this situation, you can provide a type annotation to specify the return type of GetInstance in its declaration.
See
Forcing F# type inference on generics and interfaces to stay loose
for a deep discussion of what's going on here.
Note also that in your original attempt, you don't need to "cast" (the potentially dynamic operation, using :>), instead you can just "annotate" (statically declare a type, using :) to get it to compile. But makes more sense to put the type annotation in the method declaration for GetInstance (generally, prefer addition annotations to method signatures instead of arbitrary places inside bodies).