我正在寻找F#中与Scala中的"case classes"相当的东西。
当您想要创建具有方法和字段的自定义类并仍然能够使用它们进行模式匹配时,"case classes"非常有用,正如Scala网站上的article所描述的那样。
是否有人知道F#中是否存在相同的功能?
我正在寻找F#中与Scala中的"case classes"相当的东西。
当您想要创建具有方法和字段的自定义类并仍然能够使用它们进行模式匹配时,"case classes"非常有用,正如Scala网站上的article所描述的那样。
是否有人知道F#中是否存在相同的功能?
正如Brian所提到的,有两种方式进行模式匹配:1. 通过判别联合(Discriminated unions);2. 在现有类型上使用活动模式(active pattern)。
我们从这个Scala示例开始:
abstract class Term
case class Var(name: String) extends Term
case class Fun(arg: String, body: Term) extends Term
case class App(f: Term, v: Term) extends Term
这个面向对象的设计可以翻译成F#中的区分联合类型(discriminated unions, DU):
type Term =
Var of string
| Fun of string * Term
| App of Term * Term
let eval (t: Term) =
match t with
| Var (name) -> ...
| Fun (para, body) -> ...
| App (t1, t2) -> ...
请注意,您可以在此Term
类型上定义方法和属性:
type Term =
Var of string
| Fun of string * Term
| App of Term * Term
with
member x.Type() =
match x with
| Var _ -> 0
| Fun _ -> 1
| App _ -> 2
您不能在其子类型(Var
,Fun
和App
)上定义方法。
在Term
上定义的方法是不可变的。
一旦定义了DU,就无法扩展它。想象一下,现在您需要向Term
添加一个For
子类型。然后,您必须更改许多代码,其中匹配模式为Term
。
而在oo设计中,则不太成问题。因为新的子类型可以携带自己的实现。
在F#中,当您想要构建对子类型的简洁类型匹配时,应首先考虑DU。但它也有明显的限制。我认为活动模式匹配更等同于Scala中的case类(我只读过一点Scala):
// define the classes for different term types
[<AbstractClass>]
type Term() =
abstract Value: int with get
type Var(name:string) =
inherit Term()
override x.Value =
0
member x.Name with get() = name
type Fun(name:string, body:Term) =
inherit Term()
override x.Value =
0
member x.Name with get() = name
member x.Body with get() = body
type App(t1:Term, t2:Term) =
inherit Term()
override x.Value =
0
member x.Term1 with get() = t1
member x.Term2 with get() = t2
// the pattern function
let (|TVar|TFun|TApp|) (x:Term) =
match x with
| :? Var ->
let y = x :?> Var
TVar(y.Name)
| :? Fun ->
let y = x :?> Fun
TFun(y.Name, y.Body)
| :? App ->
let y = x :?> App
TApp(y.Term1, y.Term2)
使用活动模式的eval
函数:
let eval2 (t:Term) =
match t with
| TVar (name) -> 0
| TFun (name, body) -> 0
| TApp (t1, t2) -> 0
活动模式结合了函数式编程和面向对象编程的优点。
您还可以参考 Don Syme 的原始论文关于活动模式的介绍。
区分联合?您可以向它们添加成员方法。或者,您可以在现有类上使用活动模式。