Подтвердить что ты не робот

Эквивалент класса Scala "case class" в F #

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

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

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

4b9b3361

Ответ 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

Эта конструкция OO может быть переведена на дискриминированные объединения (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

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

  • вы не можете определить методы по своим подтипам: Var, Fun и App.

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

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

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

В F #, DU следует сначала рассмотреть, когда вы хотите создать сжатый тип соответствия по подтипам. Но он также имеет очевидные ограничения. Я думаю, что сопоставление шаблонов действий больше соответствует классу case в 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

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

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

Вы можете также ссылаться на оригинальную бумагу по активному шаблону дона Симэ.

Ответ 2

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