Skip to content

Instantly share code, notes, and snippets.

@vzarytovskii
Last active November 7, 2022 11:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save vzarytovskii/920313732ff0deb2de819614d42e131b to your computer and use it in GitHub Desktop.
Save vzarytovskii/920313732ff0deb2de819614d42e131b to your computer and use it in GitHub Desktop.
fsharp7.md
post_title username microsoft_alias featured_image categories summary desired_publication_date
What’s new in F# 7
fsharp512.png
F#, .NET, .NET Core
F# 7 is now released
2022-11-15

We’re happy to announce the availability of F# 7, shipping with .NET 7 and Visual Studio 2022. Check out the next step to making it easier for you to write robust, succinct and performant code. You can get F# 7 in the following ways:

F# 7 continues the journey to make F# simpler and more performant as well as improving interop with new C# features. Syntax for the F# specific feature SRTP is simplified. Support has been added for Static abstract members support in interfaces and consumption of C# required members and init scope. The F# compiler is improved to offer reference assemblies, trimmability, better code gen, ARM64 support, performance enhancements and bug fixes.

To learn more about F#, see Interview with F# designer Don Syme (part 1 / part 2), Betatalks #66 and previous year's The .NET Conf Focus Day on F#.

If you're interested in more advanced topics, see Fast F# series by Matthew Crews, F# community compiler sessions.

To stay up to date, check out Sergey Tihon's F# weekly, follow @fsharporg on Twitter, and join the F# Software Foundation and F# community to get the latest news and updates.

Static abstract members support in interfaces

Static abstract members support in interfaces is a new feature of .NET 7. One notable application is generic math.

We are adding a way of declaring, calling and implementing static abstract members in interfaces.

First, let's declare an interface with a static abstract member:

type IAddition<'T when 'T :> IAdditionOperator<'T>> =
    static abstract op_Addition: 'T * 'T -> 'T

Note The code above will produce FS3535 warning - Declaring "interfaces with static abstract methods" is an advanced feature. See <https://aka.ms/fsharp-iwsams> for guidance. You can disable this warning by using '#nowarn "3535"' or '--nowarn:3535'.

Next, we can implement it ('T * 'T is the F# signature for a function with two parameters of type `T):

type IAddition<'T when 'T :> IAddition<'T>> =
    static abstract op_Addition: 'T * 'T -> 'T

type Number<'T when IAddition<'T>>(value: 'T) =
    member _.Value with get() = value
    interface IAddition<Number<'T>> with
        static member op_Addition(a, b) = Number(a.Value + b.Value)

This will allow us to write generic functions that can be used with any type that implements IAddition interface:

let add<'T when IAddition<'T>>(x: 'T) (y: 'T) = 'T.op_Addition(x,y)

or in the operator form:

let add<'T when IAddition<'T>>(x: 'T) (y: 'T) = x + y

This is a runtime feature and can be used with any static methods or properties, you can see a few more examples below.

type ISinOperator<'T when 'T :> ISinOperator<'T>> =
    static abstract Sin: 'T -> 'T

let sin<'T when ISinOperator<'T>>(x: 'T) = 'T.Sin(x)

This feature can also be used with BCL built-in types (such as INumber<'T>), for example:

open System.Numerics

let sum<'T, 'TResult when INumber<'T> and INumber<'TResult>>(values: 'T seq) =
    let mutable result = 'TResult.Zero
    for value in values do
        result <- result + 'TResult.CreateChecked(value)
    result

These simplified examples show how static abstract members in interfaces work. You are most likely to use this feature if you are a library author or you write specialized arithmetic functions.

Making working with SRTPs easier

Note

SRTPs or Statically Resolved Type Parameters are type parameters that are replaced with an actual type at compile time instead of at run time. F# 7 simplifis the syntax used for defining SRTPs.

As a quick refreshment on what SRTPs are, and how they're used, let's declare a function named average that takes an array of type T where type T is a type that has at least the following members:

  • An addition operator ((+) or op_Addition)
  • A DivideByInt static method, which takes a T and an int and returns a T
  • A static property named Zero that returns a T
let inline average< ^T
                   when ^T: (static member (+): ^T * ^T -> ^T)
                   and  ^T: (static member DivideByInt : ^T * int -> ^T)
                   and  ^T: (static member Zero : ^T)>
                   (xs: ^T array) =
    let mutable sum : ^T = (^T : (static member Zero: ^T) ())
    for x in xs do
        sum <- (^T : (static member op_Addition: ^T * ^T -> ^T) (sum, x))
    (^T : (static member DivideByInt: ^T * int -> ^T) (sum, xs.Length))

^T here is a type parameter, and ^T: (static member (+): ^T * ^T -> ^T), ^T: (static member DivideByInt : ^T * int -> ^T), and ^T: (static member Zero : ^T) are constraints for it.

We are making some improvements.

You no longer need to use a dedicated type parameter character (^), a single tick character (') can be used instead, compiler will decide whether it's static or generic based on the context - whether the function is `inline`` and if it has constraints.

We are also adding a new simpler syntax for calling constraints, which is more readable and easier to write:

let inline average<'T
                when 'T: (static member (+): 'T * 'T -> 'T)
                and  'T: (static member DivideByInt : 'T * int -> 'T)
                and  'T: (static member Zero : 'T)>
                (xs: 'T array) =
    let mutable sum = 'T.Zero
    for x in xs do
        sum <- sum + x
    'T.DivideByInt(sum, xs.Length)

Finally, we've added the ability to declare constraints in groups:

type AverageOps<'T when 'T: (static member (+): 'T * 'T -> 'T)
                   and  'T: (static member DivideByInt : 'T*int -> 'T)
                   and  'T: (static member Zero : 'T)> = 'T

And a simpler syntax for self-constraints, which are constraints that refer to the type parameter itself:

let inline average<'T when AverageOps<'T>>(xs: 'T array) =
    let mutable sum = 'T.Zero
    for x in xs do
        sum <- sum + x
    'T.DivideByInt(sum, xs.Length)

Simplified call syntax also works with instance members:

type Length<'T when 'T: (member Length: int)> = 'T
let inline len<'T when Length<'T>>(x: 'T) =
    x.Length

We believe that those changes will make working with SRTPs easier and more readable.

Required properties checking

C# 11 introduced new required modifier for properties, F# 7 supports consuming classes with required properties and enforcing the constraint:

Consider the following data type, defined in the C# library:

public sealed class Person
{
    public required string Name { get; set; }
    public required string Surname { get; set; }
}

When using from F# code, compiler will make sure required properties are getting properly initialized:

let person = Person(Name = "John")

The code above will compile correctly, but if we try to omit any of the required properties, we will get a compile-time diagnostic:

FS3545: The following required properties have to be initalized:
    property Person.Surname: string with get, set

Init scope and init-only properties

In F# 7 we are tightening the rules for init-only properties so that they can only be initialized within the init scope. This is a new compile-time check and is a breaking change, and will only be applied starting F# 7, see examples below.

Given the following C# data type:

public sealed class Person
{
    public int Id { get; init; }
    public int Name { get; set; }
    public int Surname { get; set; }
    public Person Set() => this;
}

Before, in F# 6, the following code would've compiled and mutated the property Id of the Person:

let person = Person(Id = 42, Name = "John", Surname = "Doe")
person.Id <- 123
person.set_Id(123)
person.Set(Id=123)

In F# 7, we are changing this to be a compile-time error:

Error FS0810 Init-only property 'Id' cannot be set outside the initialization code. See https://aka.ms/fsharp-assigning-values-to-properties-at-initialization
Error FS0810 Cannot call 'set_Id' - a setter for init-only property, please use object initialization instead. See https://aka.ms/fsharp-assigning-values-to-properties-at-initialization
Error FS0810 Init-only property 'Id' cannot be set outside the initialization code. See https://aka.ms/fsharp-assigning-values-to-properties-at-initialization

Reference assemblies support

Starting F# 7, compiler can generate and properly consume reference assemblies.

You can generate reference assemblies by:

  • Adding ProduceReferenceAssembly MSBuild project property to your fsproj (<ProduceReferenceAssembly>true</ProduceReferenceAssembly>) file or msbuild flags (/p:ProduceReferenceAssembly=true).
  • Using --refout or --refonly compiler options.

We are looking forward to your feedback on this feature.

Other changes

Other changes in F# 7 include:

  • Added support for N-d arrays up to rank 32.
  • Result module functions parity with Option.
  • Fixes in resumable state machines codegen for the tasks builds.
  • Better codegen for compiler-generated side-effect-free property getters.
  • For better trimmability, reflection-free codegen flag for F# compiler `--reflectionfree":
    • Skip emitting "%A" ToString implementation for records, unions and structs.
  • Trimmabillity improvements for F# Core - added ILLink.LinkAttributes.xml and ILLink.LinkAttributes.xml for FSharp.Core, which allows trimming compile-time resources and attributes for runtime-only FSharp.Core dependency.
  • ARM64 platform-specific compiler and ARM64 target support in F# compiler. Dependency manager #r caching support.
  • Parallel type-checking and project-checking support (experimental, can be enabled via VS setting, or by tooling authors).
  • Miscellaneous bugfixes and improvements.

RFCs for F# 7 can be found here.

General Improvements in .NET 7

.NET 7 brought a myriad improvements, which F# 7 will benefit from - various arm64 performance improvements, and general performance improvements.

Thanks and Acknowledgments

F# is developed as a collaboration between the .NET Foundation, the F# Software Foundation, their members and other contributors including Microsoft. The F# community is involved at all stages of innovation, design, implementation and delivery and we're proud to be a contributing part of this community.

Many people have contributed directly and indirectly to F# 7, including all who have contributed to the F# Language Design Process through fsharp/fslang-suggestions and fsharp/fslang-design repositories.

Adam Boniecki, Brett V. Forsgren, Don Syme, Jon Sequeira Kevin Ransom, Petr Pokorný, Petr Semkin, Tomáš Grošup, Vlad Zarytovskii, Will Smith contributed directly as part of F# team at Microsoft.

Florian Verdonck contributed 72 PRs, including work on parallel type-checking improvements, tons of improvements to the syntax trees, which benefit all tooling in general and Fantomas source code formatter in particular.

Eugene Auduchinok contributed [26 PRs including a bunch of improvements and optimizations in the parser, IL reading, completions, compiler service caching and more.

Our new contributor Edgar Gonzalez 🥳 contributed 17 PRs with tons of improvements and fixes around attributes processing, RequiredQualifiedAccess & lower-cased DU cases relaxations and whole bunch of bugfixes.

kerams contibuted 13 PRs for records, types, unions, enums, lambda variables completions, IL gen improvements, and more.

Other direct contributors to the dotnet/fsharp repository in the F# 7.0 time period include teo-tsirpanis, DedSec256, baronfel, leolorenzoluis, dawedawe, tmat, marcin-krystianc, cartermp, pirrmann, safesparrow, omppye, Happypig375, ncave, thinkbeforecoding, MichaelSimons, tboby, mmitche, nosami, jonfortescue, smoothdeveloper, abelbraaksma, uxsoft.

Many other people are contributing to the rollout of F# 7 and .NET 7 in Fable, Ionide, Bolero, FSharp.Data, Giraffe, Saturn, SAFE Stack, WebSharper, FsCheck, DiffSharp, Fantomas and other community-delivered technologies.

Contributor Showcase

In this and future announcements, we will highlight some of the individuals who contribute to F#. This text is written in the contributors’ own words:

I'm Edgar Gonzalez, and I live between Albacete(Spain) and London(Uk), where I'm a Mobile Developer at Fund Ourselves.

I'm new to the .NET ecosystem. Previously I was a member of the Spanish Paratroopers Brigade "Almogávares" VI, where I served as a Corporal first class (2004-2017).

I started programming five years ago, interested in mobile development with C#, and around the same time, I was introduced to F# by Frank A. Krueger using Xamarin.iOS

Last year I moved to F#, and during my journey realized that there is room for improvement regarding compiler error reporting, so I decided to get involved and help make F# simple for newcomers like me.

Why do I like F#? it has a clean and lightweight syntax, is expression-oriented, exhaustive pattern matching, and discriminated unions.

I look forward to continuing to help F# to be even better, focusing on making it easy for newcomers.

Thanks to Timothé Larivière and Florian Verdonck for helping me get started with open source.

Contributor photo

I’m Florian Verdonck, an independent software consultant with a passion for open-source development. My F# open-source journey started in 2017, as part of the F# foundation mentorship program. My mentor, Anthony Lloyd, and I started contributing to the Fantomas project. Maintaining led to contributing, and later, I was adding to F# editor and compiler tooling. Several great mentors helped me get my contributions accepted and my pull requests merged in and I’m grateful to all of them.

Being inspired to contribute to the wonderful F# community is one thing. Having the resources to do it properly is another. Luckily, I found customers that share my vision of improving open source by active collaboration.

I’ve been fortunate to work with the open-source division of G-Research, a leading quantitative finance research firm. It is actively contributing to the open-source software it uses in-house. The leaders there believe that targeted open-source efforts can improve the operational efficacy of their engineers and encourage me in my work.

Contributor photo

TODO: Florian

Contributor photo

@T-Gro
Copy link

T-Gro commented Oct 26, 2022

and a simpler syntax for self-constraints

  • Does any of the examples refer to it? This is not obviously clear to me.

@T-Gro
Copy link

T-Gro commented Oct 26, 2022

Addidng ProduceReferenceAssembly MSBuild project
typo
=> Adding

  • add full example:
    <ProduceReferenceAssembly>false</ProduceReferenceAssembly>

@T-Gro
Copy link

T-Gro commented Oct 26, 2022

enums, and lambd variables completions, IL gen
=>
enums, lambda variable completions, IL gen

@psfinaki
Copy link

SRTPs or Statically Resolved Type Parameters are type parameters that is replaced with an actual type at compile time instead of at run time.

ARE replaced

Static abstract members support in interfaces

Maybe worth explicitly noting that we actually don't recommend all that stuff.

Addidng ProduceReferenceAssembly MSBuild project property to your fsproj file

Adding

Using --refout or --refout compiler options.

I guess something else was meant to be here.

Dependecy manager

Dependency

type checking immprovements

improvements

General notes:

  • good stuff, focus on the community is awesome
  • maybe it is worth putting the first sections under some "interoperability" word umbrella

@dsyme
Copy link

dsyme commented Oct 28, 2022

It's all looking really good!

For order of major sections I'd say use

  • Static abstract methods
  • SRTP simplifications
  • Records interop
  • Improving native and trimmable compilation
  • ARM64
  • Parallel type-checking

RFCs are all here: https://github.com/fsharp/fslang-design/tree/main/FSharp-7.0. Please add new ones if there's anything worthy of an RFC missing.

maybe it is worth putting the first sections under some "interoperability" word umbrella

Yes the major theme here is about modern interop for sure. The first intro should be written along those lines.

@KathleenDollard
Copy link


post_title: What’s new in F# 7
username:
microsoft_alias:
featured_image: fsharp512.png
categories: F#, .NET, .NET Core
summary: F# 7 is now released
desired_publication_date: 2022-11-15

We’re happy to announce the availability F# 7, shipping with .NET 7 and Visual Studio 2022. [[Check out]] the next step to making it easier for you to write robust, succinct and performant code. You can get F# 7 in the following ways:

[[F# 7 continues the journey to make F# simpler and more performant as well as improving interop with new C# features. Syntax for the F# specific feature SRTP is simplified. Support has been added for Static abstract members support in interfaces and consumption of C# required members and init scope. The F# compiler is improved to offer reference assemblies, trimmability, better code gen, ARM64 support, performance enhancements and bug fixes..]]

The F# community

TODO, UPDATE: To learn more about F#, see The .NET Conf Focus Day on F# including the F# Bonanza, Guido van Rossum Learns F# and Starting Your F# Journey.

Making working with SRTPs easier

Note

SRTPs or Statically Resolved Type Parameters are type parameters that are replaced with an actual type at compile time instead of at run time. [[F# 7 simplifis the syntax used for defining SRTPs.]][[Can we add a sentence on when you should use SRTP, perf?]]

As a quick refreshment on what SRTPs are, and how they're used, let's declare a function named average that takes an array of type T where type T is a type that has at least the following members:

  • An addition operator ((+) or op_Addition)
  • A DivideByInt static method, which takes a T and an int and returns a T
  • A static property named Zero that returns a T
let inline average< ^T
                   when ^T: (static member (+): ^T * ^T -> ^T)
                   and  ^T: (static member DivideByInt : ^T * int -> ^T)
                   and  ^T: (static member Zero : ^T)>
                   (xs: ^T array) =
    let mutable sum : ^T = (^T : (static member Zero: ^T) ())
    for x in xs do
        sum <- (^T : (static member op_Addition: ^T * ^T -> ^T) (sum, x))
    (^T : (static member DivideByInt: ^T * int -> ^T) (sum, xs.Length))

^T here is a type parameter, and ^T: (static member (+): ^T * ^T -> ^T), ^T: (static member DivideByInt : ^T * int -> ^T), and ^T: (static member Zero : ^T) are constraints for it.

We are making some improvements.

[[You no longer need ]]to use a dedicated type parameter character (^), a single tick character (') can be used instead, compiler will decide whether it's static or generic based on the context - whether the function is `inline`` and if it has constraints.

We are also adding a new simpler syntax for calling constraints, which is more readable and easier to write:

let inline average<'T
                when 'T: (static member (+): 'T * 'T -> 'T)
                and  'T: (static member DivideByInt : 'T * int -> 'T)
                and  'T: (static member Zero : 'T)>
                (xs: 'T array) =
    let mutable sum = 'T.Zero
    for x in xs do
        sum <- sum + x
    'T.DivideByInt(sum, xs.Length)

Finally, we've added ability to declare constraints in groups:

type AverageOps<'T when 'T: (static member (+): 'T * 'T -> 'T)
                   and  'T: (static member DivideByInt : 'T*int -> 'T)
                   and  'T: (static member Zero : 'T)> = 'T

And a simpler syntax for self-constraints, which are constraints that refer to the type parameter itself:

let inline average<'T when AverageOps<'T>>(xs: 'T array) =
    let mutable sum = 'T.Zero
    for x in xs do
        sum <- sum + x
    'T.DivideByInt(sum, xs.Length)

Simplifed call syntax also works with instance members:

type Length<'T when 'T: (member Length: int)> = 'T
let inline len<'T when Length<'T>>(x: 'T) =
    x.Length

We believe that those changes will make working with SRTPs easier and more readable.

Static abstract members support in interfaces

Static abstract members support in interfaces is a new feature of .NET 7. One notable application is generic math.

We are adding a way of declaring, calling and implementing static abstract members in interfaces.

First, let's declare an interface with static abstract member:

type IAddition<'T when 'T :> IAdditionOperator<'T>> =
    static abstract op_Addition: 'T * 'T -> 'T

Note The code above will produce FS3535 warning - Declaring "interfaces with static abstract methods" is an advanced feature. See <https://aka.ms/fsharp-iwsams> for guidance. You can disable this warning by using '#nowarn "3535"' or '--nowarn:3535'.

Next, we can implement it [[('T * 'T is the F# signature for a function with two parameters of type `T)]]:

type IAddition<'T when 'T :> IAddition<'T>> =
    static abstract op_Addition: 'T * 'T -> 'T

type Number<'T when IAddition<'T>>(value: 'T) =
    member _.Value with get() = value
    interface IAddition<Number<'T>> with
        static member op_Addition(a, b) = Number(a.Value + b.Value)

This will allow us to write generic functions that can be used with any type that implements IAddition interface:

let add<'T when IAddition<'T>>(x: 'T) (y: 'T) = 'T.op_Addition(x,y)

or in the operator form:

let add<'T when IAddition<'T>>(x: 'T) (y: 'T) = x + y

This is a runtime feature and can be used with any static methods or properties, you can see a few more examples below.

type ISinOperator<'T when 'T :> ISinOperator<'T>> =
    static abstract Sin: 'T -> 'T

let sin<'T when ISinOperator<'T>>(x: 'T) = 'T.Sin(x)

This feature can also be used with BCL built-in types (such as INumber<'T>), for example:

open System.Numerics

let sum<'T, 'TResult when INumber<'T> and INumber<'TResult>>(values: 'T seq) =
    let mutable result = 'TResult.Zero
    for value in values do
        result <- result + 'TResult.CreateChecked(value)
    result

[[These simplified examples show how static abstract members in interfaces work. You are most likely to use this feature if you are a library author or you write specialized arithmetic functions.]]

Required properties checking

[[]]
[[ Whether we put it here or it's own section, I think we should include respecting init scope. I would tend to put it in a separate small section. ]]

C# 11 introduced new required modifier for properties, F# 7 supports consuming classes with required properties and enforcing the constraint:

Consider the following data type, defined in C# library:

public sealed class Person
{
    public required string Name { get; set; }
    public required string Surname { get; set; }
}

When using from F# code, compiler will make sure required properties are getting properly initialized:

let person = Person(Name = "John", Surname = "Doe")

The code above will compile correctly, but if we try to omit any of the required properties, we will get a compile-time diagnostic:

FS3545: The following required properties have to be initalized:
    property Person.Surname: string with get, set

Reference assemblies support

Starting F# 7, compiler can generate reference assemblies.

[[I found this paragraph to be confusing. Can you clarify, or we can work together on it.]]
A reference assembly only has references for what it needs in the API surface. The real assembly may have additional references related to specific implementations.

You can generate reference assemblies by:

  • Adding ProduceReferenceAssembly MSBuild project property to your fsproj (<ProduceReferenceAssembly>true</ProduceReferenceAssembly>) file or msbuild flags (/p:ProduceReferenceAssembly=true).
  • Using --refout or --refonly compiler options.

We are looking forward to your feedback on this feature.

Other changes

Other changes in F# 7 include:

  • Fixes in resumable state machines codegen for the tasks builds.
  • Better codegen for compiler-generated side-effect-free property getters.
  • [[For better trimmability, r]]eflection-free codegen flag for F# compiler `--reflectionfree":
    • Skip emitting "%A" ToString implementation for records, unions and structs.
  • Trimmabillity improvements for F# [[Core]] - added ILLink.LinkAttributes.xml and ILLink.LinkAttributes.xml for FSharp.Core, which allows trimming compile-time resources and attributes for runtime-only FSharp.Core dependency.
  • ARM64 platform-specific compiler and ARM64 target support in F# compiler.[[ ]]Dependency manager #r caching support.
  • Parallel type-checking and project-checking support (experimental, can be enabled via VS setting, or by tooling authors).
  • Miscellaneous bugfixes and improvements.

General Improvements in .NET 7

TODO

General Improvements in Visual Studio

TODO

What's next

TODO

Team news

TODO

Thanks and Acknowledgments

F# is developed as a collaboration between the .NET Foundation, the F# Software Foundation, their members and other contributors including Microsoft. The F# community is involved at all stages of innovation, design, implementation and delivery and we're proud to be a contributing part of this community.

Many people have contributed directly and indirectly to F# 7, including all who have contributed to the F# Language Design Process through fsharp/fslang-suggestions and fsharp/fslang-design repositories.

Adam Boniecki, Brett V. Forsgren, Don Syme, Kevin Ransom, Petr Pokorný, Petr Semkin, Tomáš Grošup, Vlad Zarytovskii, Will Smith contributed directly at Microsoft.

Florian Verdonck [[contributed]] 72 PRs, including work on parallel type-checking improvements, tons of improvements to the syntax trees, which benefit [[all]] tooling in general and Fantomas source code formatter in particular.

Eugene Auduchinok [[contributed]] 26 PRs including bunch of improvements and optimizations in [[the]] parser, IL reading, completions, compiler service caching and more.

Our new contributor Edgar Gonzalez 🥳 [[contributed]] 17 PRs with tons of improvements and fixes around attributes processing, RequiredQualifiedAccess & lower-cased DU cases relaxations and whole bunch of bugfixes.

kerams [[contibuted]] 13 PRs for records, types, unions, enums, and lambda variables completions, IL gen improvements, and more.

Other direct contributors to the dotnet/fsharp repository in the F# 7.0 time period include teo-tsirpanis, DedSec256, baronfel, leolorenzoluis, dawedawe, tmat, marcin-krystianc, cartermp, pirrmann, safesparrow, omppye, Happypig375, ncave, thinkbeforecoding, MichaelSimons, tboby, mmitche, nosami, jonfortescue, smoothdeveloper, abelbraaksma, uxsoft
.

Many other people are contributing to the rollout of F# 7 and .NET 7 in Fable, Ionide, Bolero, FSharp.Data, Giraffe, Saturn, SAFE Stack, WebSharper, FsCheck, DiffSharp, Fantomas and other community-delivered technologies.

Contributor Showcase

In this and future announcements, we will highlight some of the individuals who contribute to F#. This text is written in the contributors’ own words:

I'm Edgar Gonzalez, and I live between Albacete(Spain) and London(Uk), where I'm a Mobile Developer at Fund Ourselves.

I'm new to the .NET ecosystem. Previously I was a member of the Spanish Paratroopers Brigade "Almogávares" VI, where I served as a Corporal first class (2004-2017).

I started programming five years ago, interested in mobile development with C#, and around the same time, I was introduced to F# by Frank A. Krueger https://twitter.com/praeclarum using Xamarin.iOS

Last year I moved to F#, and during my journey realized that there is room for improvement regarding compiler error reporting, so I decided to get involved and help make F# simple for newcomers like me.

Why do I like F#? it has a clean and lightweight syntax, is expression-oriented, exhaustive pattern matching, and discriminated unions.

I look forward to continuing to help F# to be even better, focusing on making it easy for newcomers.

Thanks to Timothé Larivière [https://twitter.com/Tim_Lariviere] and Florian Verdonck [https://twitter.com/verdonckflorian] for helping me get started with open source.

Contributor photo

TODO: Janusz and Florian

Contributor photo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment