Choose implementation at compile time in F# - f#

Most programming languages have some way of choosing an implementation at compile-time based on types. Function overloading is a common way of doing this. Using templates (in C++ or D possibly with constraits) is another option.
But in F#, I cannot find out how to do this without using class methods, and thus loosing some nice properties like currying.
let f (a:int) =
Gives Duplicate definition of 'f'
F# has statically resolved type parameters, but I don't how I can use this..
let f (a:^T) =
match T with
Gives The value or constructor of T is not defined at match T
let f (a:^T) =
match a with
| :> int as i ->
Gives Unexpected symbol ':>' in expression
let f (a:^T) =
match ^a with
| :> int as i ->
Gives Unexpected infix operator in expression

If you want to write a function that behaves differently for different types and is an ordinary F# function, then static member constraints let you do that. However, if you want to write idiomatic F# code, then there are other options:
Here is a good example showing how you can use static member constraints to do this
F# collections use different module for each type, so there is Array.map, List.map, Seq.map etc. This is idiomatic style for functional F# libraries.
FSharpChart is an example of a library that uses overloaded methods. Note that you can use static methods, so you can write Chart.Line [ ... ] and it will pick the right overload.
If you want to write generic numeric code, then I recently wrote a tutorial that covers this topic.
So, I would be a bit careful before using static constraints - it is not entirely idiomatic (e.g. not commonly used in standard libraries) and so it may cause some confusion. But it is quite powerful and certainly useful.
The key is that simply following patterns that work well in other languages might not give you the best results in F#. If you can provide a concrete example of what you're trying to do, then you might get a better results.

Related

What's the advantage of having a type to represent a function?

What's the advantage of having a type represent a function?
For example, I have observed the following snippet:
type Soldier = Soldier of PieceProperties
type King = King of PieceProperties
type Crown = Soldier -> King
Is it just to support Partial Application when additional args have yet to be satisfied?
As Fyodor Soikin says in the comments
Same reason you give names to everything else - values, functions,
modules, etc.
In other words, think about programming in assembly which typically does not use types, (yes I am aware of typed assembly) and all of the problems that one can have and then how many of those problems are solved or reduced by adding types.
So before you programmed with a language that supported functions but that used static typing, you typed everything. Now that you are using F# which has static typing and functions, just extend what you have been using typing for but now add the ability to type the functions.
To quote Benjamin C. Pierce from "Types and Programming Languages"
A type system is a tractable syntactic method for proving the absence
of certain program behaviors by classifying phrases according to the
kinds of values they compute.
As noted in "Types and Programming Languages" Section 1.2
What Type Systems Are Good For
Detecting Errors
Abstraction
Documentation
Language Safety
Efficiency
TL;DR
One of the places that I find named type function definitions invaluable is when I am building parser combinators. During the construction of the functions I fully type the functions so that I know what the types are as opposed to what type inferencing will infer they are which might be different than what I want. Since the function types typically have several parameters it is easier to just give the function type a name, and then use that name everywhere it is needed. This also saves time because the function definition is consistent and avoid having to debug an improperly declared function definition; yes I have made mistakes by doing each function type by hand and learned my lesson. Once all of the functions work, I then remove the type definitions from the functions, but leave the type definition as comments so that it makes the code easier to understand.
A side benefit of using the named type definitions is that when creating test cases, the typing rules in the named function will ensure that the data used for the test is of the correct type. This also makes understanding the data for the test much easier to understand when you come back to it after many months.
Another advantage is that using function names makes the code easier to understand because when a person new to the code looks at if for the first time they can spot the consistency of the names. Also if the names are meaningful then it makes understanding the code much easier.
You have to remember that functions are also values in F#. And you can do pretty much the same stuff with them as other types. For example you can have a function that returns other functions. Or you can have a list that stores functions. In these cases it will help if you are explicit about the function signature. The function type definition will help you to constrain on the parameters and return types. Also, you might have a complicated type signature, a type definition will make it more readable. This maybe a bit contrived but you can do fun(ky) stuff like this:
type FuncX = int -> int
type FuncZ = float -> float -> float
let addxy (x:int) :FuncX = (+) x
let subxy :FuncX = (-) x
let addz (x:float) :FuncZ =
fun (x:float) -> (fun y -> x + y)
let listofFunc = [addxy 10;addxy 20; subxy 10]
If you check the type of listofFunc you will see it's FuncX list. Also the :FuncX refers to the return type of the function. But we could you use it as an input type as well:
let compFunc (x:FuncX) (z:FuncX) =
[(x 10);(z 10)]
compFunc (addxy 10) (addxy 20)

Why can't we satisfy F# static member constraints with type extensions?

I'd like to be able to extend types from other libraries with static methods to enable generic arithmetic. Take, for example, the newly minted SIMD-friendly fixed-size VectorN types from Microsoft. They define Zero, they define (+), they define (/), but I can't use Array.average on them because they don't define DivideByInt, which I'd be happy to:
open System.Numerics
type Vector2f with
static member DivideByInt (v:Vector2f) (i:int) = v / Vector2f(single i, single i)
let bigArray : Vector2f[] = readABigFile()
printf "the average is %A" (Array.average bigArray)
But it won't let me compile, complaining
error FS0001: The type 'Vector2f' does not support the operator 'DivideByInt'
Why does this limitation exist in the F# compiler?
(Edit: essentially the same question was asked previously.)
It is not currently possible to define an operator overload in a type extension. There is an F# language user voice item for this (with quite a lot of votes) and so this is something that might change in future versions of F# (I think it would be great addition that fits nicely with the F# design).
If you absolutely need something like this today, you can either create a lightweight wrapper for your type that adds the operators, or you can use a (somewhat scary) trick that lets you hide the standard operator with a new overloaded one. The following question has both examples: Global operator overloading in F#

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.

F# Ways to help type inference?

In Expert F# 2.0 by Don Syme, Adam Granicz, and Antonio Cisternino, pg. 44
Type inference: Using the |> operator lets type information flow from
input objects to the functions manipulating those objects. F# uses
information collected from type inference to resolve some language
constructs such as property accesses and method overloading. This
relies on information being propagated left to right thorough the text
of a program. In particular, type information to the right of a position
isn't taken into account when resolving property access and overload.
So clearly using |> can help type inference.
As always, declaring the type is also helpful.
Are there any other means/tactics that can be used to help F# type inference?
EDIT
As RamonSnir correctly pointed out one is supposed to let type inference do as much work as possible. So adding type declarations just because you can is not what one should do. Do not take this question or answers as something that should be done. I asked the question to help better understand the nuance of type inference and what might help in those occasions when type inference needs help. So if type inference can resolve all of the types without help, then don't give it any, but when it does, it would be nice to know some ways to help it.
A few points:
1) Prefer module functions to properties and methods.
List.map (fun x -> x.Length) ["hello"; "world"] // fails
List.map String.length ["hello"; "world"] // works
let mapFirst xss = Array.map (fun xs -> xs.[0]) xss // fails
let mapFirst xss = Array.map (fun xs -> Array.get xs 0) xss // works
2) Prefer methods without overloading. For example, QuickLinq Helpers define non-overloaded members to avoid a bunch of type annotation in LINQ extension methods.
3) Make use of any available information to give some hints to the type checker.
let makeStreamReader x = new System.IO.StreamReader(x) // fails
let makeStreamReader x = new System.IO.StreamReader(path=x) // works
The last example is taken from an excellent write-up about F# type inference.
To conclude, you don't often need to help F# type checker. If there is a type error, the summary from the link above gives a good fixing guideline:
So to summarize, the things that you can do if the compiler is
complaining about missing types, or not enough information, are:
Define things before they are used (this includes making sure the files are compiled in the right order)
Put the things that have "known types" earlier than things that have "unknown types". In particular, you might be able reorder pipes
and similar chained functions so that the typed objects come first.
Annotate as needed. One common trick is to add annotations until everything works, and then take them away one by one until you have
the minimum needed. Do try to avoid annotating if possible. Not only
is it not aesthetically pleasing, but it makes the code more brittle.
It is a lot easier to change types if there are no explicit
dependencies on them.

Resources