Эквивалент «case class» в Scala в F #

Я ищу в F # эквивалент «классов кейсов», доступных в Scala.

Кейсы классы очень полезны, когда вы хотите создавать собственные классы с методами и полями и при этом иметь возможность использовать их с сопоставлением с образцом, как описано в этой статье веб-сайта Scala.

Кто-нибудь знает, есть ли то же самое существует в F #?

21
задан Yin Zhu 16 June 2011 в 02:23
поделиться

1 ответ

Как упоминает Брайан, есть два способа сопоставления с образцом: 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

Этот дизайн ОО может быть переведен в различимые союзы (DU) в F #:

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

Теперь вот различия:

  1. вы не можете определить методы для его подтипов: Var, Fun и App.

  2. методы, которые вы можете определить в Term, являются неизменяемыми.

  3. невозможно расширить DU, как только оно определено. Подумайте, теперь вам нужно добавить подтип For в Term. Затем вы должны изменить много кода, где Term соответствует шаблону.

  4. в то время как в oo design, это меньше проблем. потому что новый подтип может нести свои собственные реализации.

В 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

Activity patten сочетает в себе хорошее с обеих сторон: функциональное программирование и объектно-ориентированное.

исх. здесь и здесь для моделей активности.

Вы можете также обратиться к оригинальной работе по активному образцу Дона Сайма.

27
ответ дан 29 November 2019 в 21:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: