Более высокая степень детализации при использовании типов записей в F # по сравнению с Discriminated Unions

let Method = { Name:string } //oversimplification

let method_parser =
  spaces >>. many1Satisfy isLetter .>> spaces
  |>> (fun name -> { Name=name })

Если бы я предпочел использовать размеченное объединение по методу, все было бы немного более лаконично:

let method_parser =
  spaces >>. many1Satisfy isLetter .>> spaces
  |>> Method

Я считаю, что невозможно избежать такой многословности при использовании типов записей в F #. Я прав?


person devoured elysium    schedule 24.08.2011    source источник
comment
Одноэлементный случай на самом деле является вырожденным, потому что как только имеется более одного множителя / слагаемого, запись (тип продукта) больше не эквивалентна размеченному объединению (типу суммы). И наоборот, когда вы потребляете вместо конструкции: проектировать из записи легко, тогда как сопоставление регистра в помеченном объединении может быть несколько многословным.   -  person hmakholm left over Monica    schedule 25.08.2011
comment
(Похоже, ваша правка действительно добавляет отдельный вопрос. Может быть, задать его отдельно?)   -  person Nathan Shively-Sanders    schedule 25.08.2011
comment
Забавно, что ты это сказал. Сначала я писал его как отдельную, но потом сообразил, что лучше отредактировать эту ... Я последую твоему совету.   -  person devoured elysium    schedule 25.08.2011


Ответы (1)


Запись очень похожа на размеченное объединение только с одним случаем. В некоторых случаях я бы также предпочел объединение, потому что его проще использовать. Однако у записей есть два основных преимущества:

  • Они дают имена полям, что отчасти вызывает многословие, но делает код более понятным.
    Если у вас небольшое количество полей, вы можете использовать кортеж или одинарное объединение.

  • Они позволяют использовать синтаксис { info with Name = "Tomas" } для клонирования записей.
    Если вам это не нужно, вы можете использовать стандартные классы F # (которые больше похожи на .NET)

Если вы хотите получить преимущества записей, но при этом использовать простой синтаксис для создания, тогда вы можете определить статический член для построения вашей записи:

type Info = 
  { Name : string 
    Count : int }
  static member Create(name:string, count:int) = 
    { Name = name; Count = count }

Тогда вы можете написать:

// Simple example using the above type:
let res = ("hello", 5) |> Info.Create

// I expect this would work for your type like this:
let method_parser = 
   spaces >>. many1Satisfy isLetter .>> spaces 
   |>> Method.Create
person Tomas Petricek    schedule 24.08.2011