F#中Scala"case class"的等价物

SRK*_*RKX 21 f# functional-programming scala

我正在寻找Scala中可用的F#"案例类"中的等价物.

如果您希望使用方法和字段创建自定义类,并且仍然能够将它们与模式匹配一​​起使用,则案例类非常有用,如本文 Scala网站所述.

有谁知道F#中是否存在相同的内容?

Yin*_*Zhu 27

正如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
Run Code Online (Sandbox Code Playgroud)

这个OO设计可以转换为F#中的歧视联盟(DU):

type Term = 
    Var of string 
    | Fun of string * Term 
    | App of Term * Term
Run Code Online (Sandbox Code Playgroud)

基于此DU,您可以匹配Term值以查找它是什么子类型:

let eval (t: Term) = 
    match t with
    | Var (name) -> ...
    | Fun (para, body) -> ...
    | App (t1, t2) -> ...
Run Code Online (Sandbox Code Playgroud)

请注意,您可以在此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
Run Code Online (Sandbox Code Playgroud)

现在出现了差异:

  1. 你不能在它的子类型定义方法:Var,Fun,和App.

  2. 您可以定义的方法Term是不可变的.

  3. 一旦定义了DU,就不可能扩展它.想想你现在需要添加一个For子类型Term.然后你必须更改Term模式匹配的大量代码.

  4. 而在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)
Run Code Online (Sandbox Code Playgroud)

eval使用活动模式的功能:

let eval2 (t:Term) = 
    match t with
    | TVar (name) -> 0
    | TFun (name, body) -> 0
    | TApp (t1, t2) -> 0
Run Code Online (Sandbox Code Playgroud)

Activity patten结合了双方的好东西:函数式编程和面向对象.

REF.这里这里的活动模式.

您可以进一步参考Don Syme 关于活动模式的原始论文.


Bri*_*ian 7

受歧视的工会?您可以向它们添加成员方法.或者,您可以在现有类上使用活动模式.