f# - 在 F# 中重写 Erlang

标签 f# erlang

我找到了 presentation由 Don Syme 所著,这表明 Erlang 的

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

相当于 F# 的
let rec fac = function
| 0 -> 1
| n -> n * fac (n-1)

但看起来没有办法在不失去类型安全的情况下将模式匹配用于不同的数量。例如。可以使用列表模式匹配,但类型必须是通用基本类型(例如 object ):
let concat = function
    | [x;y] -> x.ToString() + y.ToString()
    | [x] -> x.ToString()

鉴于模块中的 F# 函数不支持重载,看来使用静态类型将 Erlang 代码重写为 F# 的唯一方法是使用具有方法重载的静态类而不是模块。有没有更好的方法在 F# 中重写具有不同数量的 Erlang 函数?

一般来说,说 Erlang 的参数匹配更接近 .NET(包括 C#)的方法重载而不是 F# 的模式匹配是否正确?或者两者之间没有直接替代,例如Erlang 中可能有一个函数,具有不同的元数 + 一个守卫:
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.

在最后一种情况下,参数是不同类型的。你会如何用 F# 重写它?

最佳答案

通过稍微重新考虑问题,您可以实现接近重载的目标。与其将函数视为可变性轴,不如将输入视为可变部分。如果你这样做,你会意识到你可以achieve the same with a discriminated union .

这是一个比链接文章中的示例更人为的示例:

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

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

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

显然,不是像上面 MyArguments 那样定义这样的“愚蠢”类型。 ,您将定义一个在您正在建模的域中有意义的有区别的联合。

关于f# - 在 F# 中重写 Erlang,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36173739/

相关文章:

f# - 为什么 bindingRedirect 不影响 FSharp.Core 版本

F# 使用可区分联合的基类型

F#:从另一个列表中过滤在一个列表中找到的项目

erlang - Windows 无法在本地计算机上启动 RabbitMQ 服务

string - 在元组列表上使用 Map 并将其打印为 Erlang 中的平面字符串

erlang - 列表 :keysearch erlang 的打印输出

f# - 在 F# 中运行 ML.Net Iris 演示时,我使用 TextLoader 是否错误?

F#和xna字体问题

linux - 兼容 erlang 和 rabbitmq rpm

erlang - 如何从 erlang 进程中分离 shell?