Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rewriting Erlang in F#

Tags:

erlang

f#

I have found a presentation by Don Syme which shows that Erlang's

fac(0) -> 1
fac(N) -> N * fac(N-1).

is equivalent to F#'s

let rec fac = function
| 0 -> 1
| n -> n * fac (n-1)

But it looks like there is no way to use pattern matching for a different arity without losing type safety. E.g. one could use a list pattern matching, but then a type must be a common base type (such as object):

let concat = function
    | [x;y] -> x.ToString() + y.ToString()
    | [x] -> x.ToString()

Given that F# functions in modules do not support overloads, it looks like the only way to rewrite Erlang code into F# with static typing is to use static classes with method overloading instead of modules. Is there a better way to rewrite Erlang functions with different arity in F#?

In general, is it correct to say that Erlang's argument matching is closer to .NET's (including C#) method overloading rather than to F#'s pattern matching? Or there is no direct replacement between the two, e.g. there could be a function in Erlang with different arities + a guard:

max(x) -> x.
max(x,y) when x > y -> x.
max(x,y) -> y.
max(comparer, x, y) -> if comparer(x,y) > 0 -> x; true -> y end.

In the last case the arguments are of different types. How would you rewrite it in F#?

like image 363
V.B. Avatar asked Mar 23 '16 09:03

V.B.


1 Answers

You can achieve something close to overloading by rethinking the problem slightly. Instead of thinking about the function as the axis of variability, think of the input as the variable part. If you do that, you'll realise that you can achieve the same with a discriminated union.

Here's a more contrived example than the one in the linked article:

type MyArguments = One of int | Two of int * int

let foo = function
    | One x -> string x
    | Two (x, y) -> sprintf "%i%i" x y

Usage:

> foo (One 42);;
val it : string = "42"
> foo (Two (13, 37));;
val it : string = "1337"

Obviously, instead of defining such a 'stupid' type as the above MyArguments, you'd define a discriminated union that makes sense in the domain you're modelling.

like image 176
Mark Seemann Avatar answered Sep 21 '22 23:09

Mark Seemann