Need help understanding the F# class syntax - f#

This is a very elementary question about the F# class syntax. Here is a little code to illustrate my problem.
type AClass() as self =
member this.Something = printfn "Hello"
Basically from what I have read the "as self" will create a name to the current instance which can be used in the entire class (like "this" in C# or Java). But "member this.Something" will do the same thing, only that the scope is limited to the method body. I guess I can see when you would use which syntax. The "as self" one can be used if you need it in the constructor or something and you can use the other one if you dont need it in the constructor.
But why do I have to use the "member this.Something" syntax even if I used the "as self" one? Why does it give me an error if I just write "member Something"? What have I missed?
Take care,
Kerr

The scope of as self is the whole class, while scope of this.Something is just an individual method. You don't often need as self since using this.Something is adequate.
Regarding why you need this. in member declaration, I think it's a natural choice since in F# classes you often have let bounds and static methods as well. Having self as default would cause confusion and misuse.
Here is an example using as self in MSDN, which is not common IMO:
type MyClass2(dataIn) as self =
let data = dataIn
do
self.PrintMessage()
member this.PrintMessage() =
printf "Creating MyClass2 with Data %d" data

It sounds like you've got all the differences between global 'as xxx' and member 'yyy.' instance binding sorted out. So I guess the answer to your answer has to be it's "by design".
Folks will argue that there is a deliberate rational behind this "by design" choice, but after 4 years of programming F#, my favorite language by far, I have personally not found it very helpful in any regard.
I suspect that the real reason the language requires explicit instance bindings to variables is because is more closely reflects the underlying .NET CIL implementation. That is, languages like C# bind "this" to the instance of a class definition as a feature. Under-the-hood, both static and instance methods of a class are called in the same manner using the Call and CallVirt opcodes, where in the case of instance methods the address of "this" is loaded as the first argument to the call.
But we've certainly ventured into the territory of taste and opinion.

I don't think this is duplication at all. self's visibility to the entire class is a by-product of F#'s "intelligent" compilation of primary constructors. The constructor's arguments/bindings can be implicitly compiled to both local and member (class-level) fields. The as identifier syntax merely facilitates this references within that mutant context. I'd venture to guess, if unused, it's compiled away. Otherwise, all you've done is stored an extra reference to this as a member field (which would seem bizarre in another language, such as C#).

Related

Why is using final, with no type, considered good practice in Dart? ie `final foo = config.foo;`?

I see this recommended in the dart style guide, and copied in tons of tutorials and flutter source.
final foo = config.foo;
I don't understand it, how is this considered best practice when the readability is so poor? I have no clue what foo is here, surely final String foo = config.foo is preferable if we really want to use final?
This seems the equivalent to using var, which many consider a bad practice because it prevents the compiler from spotting errors and is less readable.
Where am I wrong?
In a lot of cases is does not really matter what type you are using as long the specific type can be statically determined by the compiler. When you are using var/final in Dart it is not that Dart does not know the type, it will just figure it out automatically based on the context. But the type must still be defined when the program are compiled so the types will never be dynamic based on runtime behavior. If you want truly dynamic types, you can use the dynamic keyword where you tell Dart "trust me, I know what I am doing with this types".
So types should still be defined where it matter most. This is e.g. for return and argument types for methods and class variables. The common factor for this types is that they are used to define the interface for using the method or class.
But when you are writing code inside a method, you are often not that interested in the specific types of variables used inside the method. Instead the focus should be the logic itself and you can often make it even more clear by using good describing variable names. As long the Dart analyzer can figure out the type, you will get autocomplete from your IDE and you can even still see the specific type from your IDE by e.g. Ctrl+Q in IntelliJ on the variable if you ends up in a situation where you want to know the type.
This is in particular the case when we are talking about the use of generics where it can be really tiresome to write the full specific type. Especially if you are using multiple generics inside each other like e.g. Map<String, List<String>>.
In my experience, Dart is really good to figure out very specific types and will complain loudly if your code cannot be determined statically. In the coming future, Dart will introduce non-null by default, which will make the Dart compiler and analyzer even more powerful since it will make sure your variable cannot be null unless this is something you specifically want and will make sure you are going to test for null when using methods which are specified to not expecting null.
About "Where am I wrong?". Well, a lot of languages have similar feature of var/final like Dart with the same design principle about the type should still be statically determined by a compiler or runtime. And even Java has introducing this feature. As a experienced Java and Dart programmer I have come to the conclusion for myself that typing inside methods are really not that important in a lot of cases as long I can still easily figure out the specific type by using an IDE when it really matters.
But it does make it more important to name your variables so they are clearly defining the purpose. But I am hoping you already are doing that. :)

Type name as identifier in F#

I just started to study F# and accidentally wrote this binding
let List = 1
Now when I try to obtain List methods such as 'filter' I get this error
error FS0039: The field, constructor or member 'filter' is not defined.
Of course using method with full type name like Microsoft.FSharp.Collections.List.filter is still working.
I'm wondering why it is possible to use type name as identifier in F# and how I can set back name List to type List from Microsoft.FSharp.Collections.
When I tried to reassign like this
type List = Microsoft.FSharp.Collections.List<'T>
I get
Error FS0039: The type parameter 'T is not defined.
Thank you!
In F# you can redefine almost everything and shadow existing definitions. This applies to both types (well actually types have a different behavior regarding shadowing, they shadow their values as you open the namespaces) and values but not interchangeably since values and type (and also modules) can somehow coexist at the same time in the scope. The compiler will do his best to find out which one is.
You are not forced to, but it's a common good practice in F# not to use let bindings in uppercase.
Regarding your second question, you are using a type parameter in the right side which doesn't exist in the left side of the assignment, it should be:
type List<'T> = Microsoft.FSharp.Collections.List<'T>
But notice that filter doesn't belong to the type. It's rather defined in the List module.
You should just rename your let binding from List to something sensible - as Gustavo mentioned, your definition is shadowing the core List module from F# and there is no way to use List to refer both to your integer and to the module. Shadowing core functions will make your code pretty confusing. It's also a good idea to use camelCase for let bindings, but that's a matter of taste.
If you insist on shadowing List, then you won't be able to call List.filter using List.filter. If you wanted something shorter, you could define module alias:
module FsList = Microsoft.FSharp.Collections.List
Note that your attempt to do something similar with List<'T> does not do the same thing, because functions such as filter are in a module named List rather than being static members of the type. With this, you can call filter using FsList.filter.

Delay the implementation of interface methods?

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 :-)

compile-time checking in Groovy

In Groovy types are optional so you can use either:
String foo = "foo"
foo.noSuchMethod()
or
def foo = "foo"
foo.noSuchMethod()
I assumed that the first example would generate a compile-time error, whereas the second would only fail at runtime. However, this doesn't appear to be the case. In my experience, a compile-time error is generated in neither case.
Am I right in assuming then that the only benefit of declaring the type of a reference is as a form of documentation, i.e. to communicate intentions to other programmers. For example, if I write a method such as:
def capitalize(String arg) {
return arg.toUpperCase()
}
This communicates the type of arguments that should be passed to the function much more effectively than:
def capitalize(def arg) {
return arg.toUpperCase()
}
Does the Groovy compiler perform any type-checking when types are specified?
Thanks,
Don
[Edit] Newer versions of Groovy do allow for compile-time static type checking. Code that uses this annotation IS faster than regular run-time Groovy, as many of the dynamic checks are skipped.
As Cesar said, type checking is a run-time process, one of the major reasons that Groovy is slower than Java (not that that's really bad).
You can see why this is, right? Given the dynamic nature of Groovy, it's near-impossible to tell if String has been extended somewhere else in your code to contain a method noSuchMethod(). The same goes for member type-checking, as it's entirely possible to remove a member of one type, and add a member of another type with the same name later in code. It's probably not common, but very possible.
The question is, how much type checking do you really need? You're calling the method, you really should know what arguments it takes, or if the method actually exists. Using compile-time checking to save you the time of looking it up isn't a core usefulness of the compiler.
In Groovy, type checking is done dynamically at runtime. The benefits of variables with type is that you can be sure that it contains the value you expect them to have, otherwise you get a runtime exception that you can catch and do whatever you need to do to handle the exception.
Compile time-checking in Groovy is close to impossible for types. Your example of
String foo = "foo"
foo.noSuchMethod()
Would work beautifully given that previously an instruction was executed along the lines of
String.metaClass.noSuchMethod { -> println "Yes there is such a method"}
One reason you might specify a type is to allow an IDE to help you.
def foo
foo.[ctrl-space]
... won't help you very much
List foo
foo.[ctrl-space]
... might (depending on the IDE) give you a choice of List's methods. Of course, a method that's not one of the choices might be a valid one to use, for the reasons given in other answers.
There are other automated software maintenance operations that benefit from clues about types. For example, refactoring.

Regarding F# Object Oriented Programming

There's this dichotomy in the way we can create classes in f# which really bothers me. I can create classes using either an implicit format or an explicit one. But some of the features that I want are only available for use with the implicit format and some are only available for use with the explicit format.
For example:
I can't use let inline* (or let alone) inside an explicitly defined class.
The only way (that I know) to define immutable public fields (not properties*) inside an implicitly defined class is the val bla : bla syntax.
But there's a redundancy here. Since I'll end up with two copy of the same immutable data, one private, one public (because in the implicit mode the constructor parameters persist throughout the class existence)
(Not so relevant) The need to use attributes for method overloading and for field's defaults is rather off putting.
Is there anyway I can work around this?
*For performance reasons
EDIT: Turns out I'm wrong about both points (Thanks Ganesh Sittampalam & MichaelGG).
While I can't use let inline in both implicit & explicit class definition, I can use member inline just fine, which I assume does the same thing.
Apparently with the latest F# there's no longer any redundancy since any parameters not used in the class body are local to the constructor.
Will be gone in the next F# release.
This might not help, but you can make members inline. "member inline private" works fine.
For let inline, you can work around by moving it outside the class and explicitly passing any values you need from inside the scope of the class when calling it. Since it'll be inlined, there'll be no performance penalty for doing this.

Resources