Моделирование домена F # с общими свойствами - PullRequest
1 голос
/ 08 июля 2020

Я не могу понять, как сделать следующее на идиоматике c F # (с небольшими поправками для ясности):

type Shared(name, label, multivalue) = 
  member val Name = name with get, set
  member val Label = label with get, set
  member val Multivalue = multivalue with get, set

type TextField(name, label, multivalue) = 
  inherit Shared(name, label, multivalue)
  member val Xslt = "" with get, set

type NumberField(name, label, multivalue) = 
  inherit Shared(name, label, multivalue)        

// helper 'create' function  
let textfield name label =
  TextField (name, label, false)

// helper 'create'  function
let numberfield name label = 
  NumberField (name, label, false)

let makemultivaluefield (field: Shared)  = 
  field.Multivalue <- true
  //field <- I would want this to return the parent type. E.g. TextField or NumberField    

// Actual code for creating / using above domain (DSL like syntax... that's the goal of this whole exercise)
let myTextField = 
  textfield "field" "field"
  |> makemultivaluefield

let myNumberField = 
  numberfield "fieldnumber" "field number label"
  |> makemultivaluefield

Вызов |> makemultivaluefield теперь возвращает unit, но я хотите, чтобы он возвращал TextField или NumberField (есть больше классов, таких как NumberField и TextField, все с теми же тремя свойствами, объявленными в Shared).

1 Ответ

2 голосов
/ 08 июля 2020

Подход с минимальным количеством изменений по сравнению с вашим примером будет примерно таким:

let makemultivaluefield<'subtype when 'subtype :> Shared> (field: 'subtype) : 'subtype = 
  field.Multivalue <- true
  field

Сделайте функцию generi c, а затем ограничьте ее подтипами вашего типа Shared. Это должно сработать для вас, если ваш реальный код не намного сложнее, чем в примере.

...