[英]Equivalent of Scala “case class” in F#
我正在尋找Scala中可用的F#中的“案例類”中的等效項。
當您想使用方法和字段創建自定義類並且仍然能夠將它們用於模式匹配時,案例類非常有用,如Scala網站上的文章所述。
誰知道F#中是否存在相同的東西?
正如Brian所提到的,模式匹配有兩種方法:1.區分聯合和2.在現有類型上使用活動模式。
讓我們從這個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
此OO設計可以轉換為F#中的歧視工會(DU):
type Term =
Var of string
| Fun of string * Term
| App of Term * Term
基於此DU,您可以匹配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中的案例類(我只讀了一點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撰寫的有關活動模式的原始論文 。
受歧視的工會? 您可以向其添加成員方法。 或者,您可以在現有的類上使用活動模式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.