Эквивалент Scala "case class" в F # - PullRequest
21 голосов
/ 15 июня 2011

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

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

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

Ответы [ 2 ]

27 голосов
/ 15 июня 2011

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

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

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

7 голосов
/ 15 июня 2011

Дискриминационные союзы?Вы можете добавить к ним методы-члены.В качестве альтернативы вы можете использовать активные шаблоны в существующем классе.

...