Which to use , abstract class or interface in F#? - f#

Been grokking F# coming from a C# background.
In C# there is a clear difference in deciding when to use interfaces and when to use abstract classes. In F# I see the two blurring almost into one. I understand under the hood that the same is being done in F# as c# as far as the CLR is concerned, but what is the "best practise" when programming in F# to use?
Should I avoid class inheritance altogether?

I think that interfaces tend to be used much more frequently than abstract classes (compared to object-oriented languages like C#).
In many cases, you don't need any of the two, because you can just write higher-order function (that takes a function as an argument, instead of taking an interface as an argument). However, sometimes you may have two functions that are always used together - in that case, you can group two functions into an interface:
// Instead of using higher-order function
val foo : (int -> string) -> (string -> int) -> ...
// ..we can define an interface
type TwoWayConversion =
abstract ToString : int -> string
abstract FromString : string -> int
val foo : TwoWayConversion -> ...
I think that this is quite useful F# programming pattern that uses interfaces in a perfectly functional style.
On the other hand, I would use abstract classes only when writing object-oriented code that is supposed to be used from C# (e.g. C# code implementing your F# abstract class) - because that's a natural extensibility point from the C# point of view. However, I think that idiomatic F# code uses different extensibility points than C# (e.g. taking function/interface as an argument), so you don't really need abstract classes.

Well, if you're debating between abstract classes and interfaces, I think your reasons for one or the other would be the same as in C#.
Maybe you should consider using functions, functional data types and modules as units of abstraction though.
If you need to write an F# library to be used in C#, then you'll probably want to use interfaces etc for your exported types.

Related

Working with classes in F# (mutability vs immutability / members vs free functions)

I am currently doing the exercism.io F# track. For everyone who doesn't know it, it's solving small problems TDD style to learn or improve a programming language.
The last two tasks were about the usage of classes in F# (or types as they are called in F#). One of the tasks uses a BankAccount that has a balance and a status (open/closed) and can be altered by using functions. The usage was like this (Taken from the test code):
let test () =
let account = mkBankAccount () |> openAccount
Assert.That(getBalance account, Is.EqualTo(Some 0.0)
I wrote the code that makes the test pass using an immutable BankAccount class that can be interacted with using free functions:
type AccountStatus = Open | Closed
type BankAccount (balance, status) =
member acc.balance = balance
member acc.status = status
let mkBankAccount () =
BankAccount (0.0, Closed)
let getBalance (acc: BankAccount) =
match acc.status with
| Open -> Some(acc.balance)
| Closed -> None
let updateBalance balance (acc: BankAccount) =
match acc.status with
| Open -> BankAccount (acc.balance + balance, Open)
| Closed -> failwith "Account is closed!"
let openAccount (acc: BankAccount) =
BankAccount (acc.balance, Open)
let closeAccount (acc: BankAccount) =
BankAccount (acc.balance, Closed)
Having done a lot of OO before starting to learn F# this one got me wondering. How do more experienced F# developers use classes? To make answering this question more simple, here are my main concerns about classes/types in F#:
Is the use of classes in a typical OO fashion discouraged in F#?
Are immutable classes preferred? ( I found them to be confusing in the above example)
What is the preferred way to access/alter class data in F#? (Class member functions and get/set or free functions which allow piping? What about static members to allow piping and providing the functions with a fitting namespace?)
I'm sorry if the question is vague. I don't want to develop bad coding habits in my functional code and i need a starting point on what good practices are.
Is the use of classes in a typical OO fashion discouraged in F#?
It's not discouraged, but it's not the first place most experienced F# developers would go. Most F# developers will avoid subclassing and OO paradigms, and instead go with records or discriminated unions, and functions to operate on them.
Are immutable classes preferred?
Immutability should be preferred when possible. That being said, immutable classes can often be represented other ways (see below).
What is the preferred way to access/alter class data in F#? (Class member functions and get/set or free functions which allow piping? What about static members to allow piping and providing the functions with a fitting namespace?)
This is typically done via functions that allow piping, though access can be done directly, as well.
For your above code, it would be more common to use a record instead of a class, and then put the functions which work on the record into a module. An "immutable class" like yours can be written as a record more succinctly:
type BankAccount = { balance : float ; status : AccountStatus }
Once you've done this, working with it becomes easier, as you can use with to return modified versions:
let openAccount (acc: BankAccount) =
{ acc with status = Open }
Note that it'd be common to put these functions into a module:
module Account =
let open acc =
{ acc with status = Open }
let close acc =
{ acc with status = Closed }
Question: Is the use of classes in a typical OO fashion discouraged in F#?
It is not against F#'s nature. I think that there are cases when this is justified.
However, usage of classes should be limited if developers want to take full advantage of F# strengths (e.g. type interference, ability to use functional patterns such as partial application, brevity) and are not constrained by legacy systems and libraries.
F# for fun and profit gives a quick summary of pros and cons of using classes.
Ouestion: Are immutable classes preferred? ( I found them to be confusing in the above example)
Sometimes yes, sometimes not. I think that immutability of classes gives you lots of advantages (it's easier to reason about type's invariants etc.) but sometimes immutable class can be a bit cumbersome to use.
I think that this question is a bit too broad - it's somewhat similar to a question if fluent interfaces are preferred in object-oriented design - the short answer is: it depends.
What is the preferred way to access/alter class data in F#? (Class member functions and get/set or free functions which allow piping? What about static members to allow piping and providing the functions with a fitting namespace?)
Piping is a canonical construct in F#, so I would go for static member. If your library is consumed in some other languages, you should include getter and setter inside class as well.
EDIT:
FSharp.org has a list of quite specific design guidelines which include:
✔ Do use classes to encapsulate mutable state, according to standard
OO methodology.
✔ Do use discriminated unions as an alternative to class hierarchies
for creating tree-structured data.
There are a few ways of looking at this question.
This could mean several things. For POCO's, immutable F# records are preferred. Then the operations on them return new records with the requisite fields changed.
type BankAccount { status: AccountStatus; balance: int }
let close acct = { acct with status = Closed } // returns a *new* acct record
So that means you've got to get past the idea of an account "object" that represents a single "thing". It's just data that you operate on to create different data, and eventually (likely) store into a database somewhere.
So rather than the OO paradigm acct.Close(); acct.PersistChanges(), you'd have let acct' = close acct; db.UpdateRecord(acct').
For "services" in a "service-oriented architecture (SOA)" however, interfaces and classes are perfectly natural in F#. For instance, if you want a Twitter API, you'd probably create a class that wraps all the HTTP calls just like you would in C#. I've seen some references to the "SOLID" ideology in F# that eschews SOA completely but I've never figured out how to make that work in practice.
Personally, I like an FP-OO-FP sandwich with Suave's FP combinators on top, a SOA using Autofac in the middle, and FP records on the bottom. I find that works well and is scalable.
FWIW also you may want do make your BankAccount a discriminated union, if Closed can't have a balance. Try this out in your code samples. One of the nice things in F# is it makes illogical states unrepresentable.
type BankAccount = Open of balance: int | Closed

Idiomatic way to implement "services" in F#

When working in F# and implementing a "service" pattern, such as wrappers around web APIs or databases or USB gadgets, what's the idiomatic way to do this? My inclination is to use e.g. IDatabase and Database, ITwitter and Twitter, ICamera and Camera interfaces and classes just like in C#, allowing for easy test mocks. But I don't want to code "C# in F#" if that's not the standard way to do it.
I considered using DU's, to represent e.g. Camera | TestCamera, but that means putting all the mock code into the production codebase, which sounds horrible. But maybe that's just my OO background speaking.
I also considered making IDatabase a record of functions. I'm still open to that idea, but it seems a bit contrived. Plus it rules out the idea of ever using an IoC controller, or any "MEF-like" plugin capability (at least that I'm aware of).
What's the "idiomatic F#" way of doing this? Just follow the C# service pattern?
As mentioned in the other answer, using interfaces is fine in F# and that might be a good way to solve the problem. However, if you use more functional transformation-oriented style of programming, you may not need them.
Ideally, most of the actual interesting code should be transformations that do not perform any effects - and so they do not invoke any services. Instead, they just take inputs and produce outputs. Let me demonstrate using a database.
Using a IDatabase service, you might write something like this:
let readAveragePrice (database:IDatabase) =
[ for p in database.GetProducts() do
if not p.IsDiscontinued then
yield p.Price ]
|> Seq.average
When written like this, you can provide a mock implementation of IDatabase to test that the averaging logic in readAveragePrice is correct. However, you can also write the code like this:
let calculateAveragePrice (products:seq<Product>) =
[ for p in products do
if not p.IsDiscontinued then
yield p.Price ]
|> Seq.average
Now you can test calculateAveragePrice without any mocking - just give it some sample products that you want to process! This is pushing the data access out from the core logic to the outside. So you'd have:
database.GetProducts() |> calculateAveragePrice // Actual call in the system
[ Product(123.4) ] |> calculateAveragePrice // Call on sample data in the test
Of course, this is a simplistic example, but it shows the idea:
Push the data access code outside of the core logic and keep the core logic as pure functions that implement transformations. Then your core logic will be easy to test - given sample inputs, they should return the correct results!
While other people here write that there's nothing wrong with using interfaces in F#, I consider interfaces nothing more than an interop mechanism that enables F# to work with code written in the other .NET languages.
When I write code in C#, I follow the SOLID principles. When used together, the Single Responsibility Principle and the Interface Segregation Principle should ultimately drive you towards defining as small-grained interfaces as possible.
Thus, even in C#, properly designed interfaces should have only a single method:
public interface IProductQuery
{
IEnumerable<Product> GetProducts(int categoryId);
}
Furthermore, the Dependency Inversion Principle implies that "clients [...] own the abstract interfaces" (APPP, chapter 11), which means that artificial bundles of methods is a poor design anyway.
The only reason to define an interface like the above IProductQuery is that in C#, interfaces are still the best mechanism for polymorphism.
In F#, on the other hand, there's no reason to define a single-member interface. Use a function instead.
You can pass in functions as arguments to other functions:
let calculateAveragePrice getProducts categoryId =
categoryId
|> getProducts
|> Seq.filter (fun p -> not p.IsDiscontinued)
|> Seq.map (fun p -> p.Price)
|> Seq.average
In this example, you'll notice that getProducts is passed as an argument to the calculateAveragePrice function, and its type is not even declared. This fits beautifully with the principle of letting the client define the interface: the type of the argument is inferred from the client's usage. It has the type 'a -> #seq<Product> (because categoryId can be any generic type 'a).
Such a function as calculateAveragePrice is a higher-order function, which is a Functional thing to do.
There's nothing wrong with using interfaces in F#.
The textbook FP approach would be to have the client take functions that implement the logic of your component as arguments, but that approach doesn't scale nicely as the number of those functions grows. Grouping them together is a good idea as it improves readability, and using interfaces for that is an idiomatic way of doing it in .NET. It makes sense especially on the boundary of well-defined components, and I think the three interfaces you cite fit that description well.
I've seen DU's used roughly the way you described (providing both production and a fake implementation), but it doesn't sit well with me either.
If anything, records of functions are not idiomatic. They're a poor man's way of bundling together behaviour in FP languages, but if there's one thing object oriented languages do right, it's bundling together behaviour. Interfaces are just a better tool for the job, especially since F# lets you create implementations inline with object expression syntax.

F# limitations of discriminated unions

I am trying to port a small compiler from C# to F# to take advantage of features like pattern matching and discriminated unions. Currently, I am modeling the AST using a pattern based on System.Linq.Expressions: A an abstract base "Expression" class, derived classes for each expression type, and a NodeType enum allowing for switching on expressions without lots of casting. I had hoped to greatly reduce this using an F# discriminated union, but I've run into several seeming limitations:
Forced public default constructor (I'd like to do type-checking and argument validation on expression construction, as System.Linq.Expressions does with it's static factory methods)
Lack of named properties (seems like this is fixed in F# 3.1)
Inability to refer to a case type directly. For example, it seems like I can't declare a function that takes in only one type from the union (e. g. let f (x : TYPE) = x compiles for Expression (the union type) but not for Add or Expression.Add. This seems to sacrifice some type-safety over my C# approach.
Are there good workarounds for these or design patterns which make them less frustrating?
I think, you are stuck a little too much with the idea that a DU is a class hierarchy. It is more helpful to think of it as data, really. As such:
Forced public default constructor (I'd like to do type-checking and argument validation on expression construction, as
System.Linq.Expressions does with it's static factory methods)
A DU is just data, pretty much like say a string or a number, not functionality. Why don't you make a function that returns you an Expression option to express, that your data might be invalid.
Lack of named properties (seems like this is fixed in F# 3.1)
If you feel like you need named properties, you probably have an inappropriate type like say string * string * string * int * float as the data for your Expression. Better make a record instead, something like AddInfo and make your case of the DU use that instead, like say | Add of AddInfo. This way you have properties in pattern matches, intellisense, etc.
Inability to refer to a case type directly. For example, it seems like I can't declare a function that takes in only one type from the
union (e. g. let f (x : TYPE) = x compiles for Expression (the union
type) but not for Add or Expression.Add. This seems to sacrifice some
type-safety over my C# approach.
You cannot request something to be the Add case, but you definitely do can write a function, that takes an AddInfo. Plus you can always do it in a monadic way and have functions that take any Expression and only return an option. In that case, you can pattern match, that your input is of the appropriate type and return None if it is not. At the call site, you then can "use" the value in the good case, using functions like Option.bind.
Basically try not to think of a DU as a set of classes, but really just cases of data. Kind of like an enum.
You can make the implementation private. This allows you the full power of DUs in your implementation but presents a limited view to consumers of your API. See this answer to a related question about records (although it also applies to DUs).
EDIT
I can't find the syntax on MSDN, but here it is:
type T =
private
| A
| B
private here means "private to the module."

What are the benefits of type inference?

I'm started to learn F#, and I noticed that one of the major differences in syntax from C# is that type inference is used much more than in C#. This is usually presented as one of the benefits of F#. Why is type inference presented as benefit?
Imagine, you have a class hierarchy and code that uses different classes from it. Strong typing allows you quickly detect which classes are used in any method.
With type inference it will not be so obvious and you have to use hints to understand, which class is used. Are there any techniques that exist to make F# code more readable with type inference?
This question assumes that you are using object-oriented programming (e.g. complex class hierarchies) in F#. While you can certainly do that, using OO concepts is mainly useful for interoperability or for wrapping some F# functionality in a .NET library.
Understanding code. Type inference becomes much more useful when you write code in the functional style. It makes code shorter, but also helps you understand what is going on. For example, if you write map function over list (the Select method in LINQ):
let map f list =
seq { for el in list -> f el }
The type inference tells you that the function type is:
val map : f:('a -> 'b) -> list:seq<'a> -> seq<'b>
This matches our expectations about what we wanted to write - the argument f is a function turning values of type 'a into values of type 'b and the map function takes a list of 'a values and produces a list of 'b values. So you can use the type inference to easily check that your code does what you would expect.
Generalization. Automatic generalization (mentioned in the comments) means that the above code is automatically as reusable as possible. In C#, you might write:
IEnumerable<int> Select(IEnumerable<int> list, Func<int, int> f) {
foreach(int el in list)
yield return f(el);
}
This method is not generic - it is Select that works only on collections of int values. But there is no reason why it should be restricted to int - the same code would work for any types. The type inference mechanism helps you discover such generalizations.
More checking. Finally, thanks to the inference, the F# language can more easily check more things than you could if you had to write all types explicitly. This applies to many aspects of the language, but it is best demonstrated using units of measure:
let l = 1000.0<meter>
let s = 60.0<second>
let speed = l/s
The F# compiler infers that speed has a type float<meter/second> - it understands how units of measure work and infers the type including unit information. This feature is really useful, but it would be hard to use if you had to write all units by hand (because the types get long). In general, you can use more precise types, because you do not have to (always) type them.

Why does functions in F# implemented in such a way?

F# function is very different from normal CLR method because of currying support. For example function
let inc a = a + 1
Will have type Microsoft.FSharp.Core.FSharpFunc<int,int>. It creates problems with C# interoperability. Functions must be designed specially to be easily called from C#.
What is the rationale behind this design? I believe that the reason is currying support. But currying can be implemented using closures. For example this code:
let add a b = a + b
let inc = add 1
can be easily transformed into this by the compiler:
let add a b = a + b
let inc = fun x -> add 1 + x
both add and inc in this case can be normal System.Func objects. I believe that there is some interesting reasons behind this design decision.
As far as I remember, the motivation for having a separate type for functions in F# was performance (in earlier versions FSharpFunc<...> was actually called FastFunc<...>). I'm not entirely sure about the recent developments (I'm sure the F# team did some tests to find out whether delegates would work in Visual Studio 2010), but here is how I understood the problem:
If you have a function add : int -> int -> int then the function could be represented as a delegate Func<int, Func<int, int>> (using the curried representation). The problem is that very often you will want to call it with both parameters like add 1 2.
Using the representation with nested Func types, this would compile to add.Invoke(1).Invoke(2).
However, when compiling function like add, the F# compiler actually creates a new class, say, AddClass which inherits from FSharpFunc<int, FSharpFunc<int, int>> and adds an additional Invoke overload with two arguments. This means that, in most of the cases, add 1 2 can be compiled to just a single call add.Invoke(1, 2).
This design makes F# code faster. It complicates the interoperability slightly, but not too much. It is fairly easy to write an F# member or function that takes a delegate:
let foo (inc : Func<int, int>) = inc.Invoke(41)
(You just need to add type annotations and then call f.Invoke - but you can also use f.Inokve as a first-class value and pass it to other functions)
My guess is that the F# representation supports big step semantics whereas System.Func does not.
The best way to interop with C# is to wrap everything in class/members. C# never has to see the inner workings of the member.

Resources