2015-01-06 3 views
2

На странице msdn, документирующей Records (F#), содержится информация record expressions для записи строительства и record patterns для деконструкции, причем последняя не называет их как таковые. Вот пример, который использует оба метода для арифметического оператора:Построение и деконструкция записей

// Simple two-dimensional generic vector defintion 
type 'a UV = 
    { U : 'a; V : 'a } 
    static member inline (+) ({ U = au; V = av }, { U = bu; V = bv }) = 
     { U = au + bu; V = av + bv } 

Это кажется громоздким и не очень читаемым. Для деконструкции в качестве альтернатив есть точечные обозначения или функции. Так как оператор точечных обозначений имеет специальное разрешение в разделе 8.4.2. . Обозначение разрешения и метки полей поля спецификации (an expression’s type may be inferred from a record label), как правило, нет необходимости комментировать. Аксессуарные функции, такие как let u { U = u } = u, не дали бы нам никаких преимуществ.

Для построения, я думаю, что случай может быть создан для функции в качестве конструктора записи. Доступ к исходному конструктору может быть ограничен:

type 'a UV = 
    internal { U : 'a; V : 'a } 
let uv u v = { U = u; V = v } 
type 'a UV with 
    static member inline (+) (a, b) = 
     uv (a.U + b.U) (a.V + b.V) 

Это идиоматическая вещь? Как упаковать такие функции в модули и обработать проблемы пространства имен?

ответ

4

Короткий ответ: Я не думаю, что в настоящий момент существует общее соглашение, поэтому в конце концов это будет личное решение.

Чтобы подвести итог, что вы получаете бесплатно с записями в F # является:

  • Construct: { U = u; V = v } (кронштейн нотации)

  • деконструкции: let u = record.u (точка-обозначения) и let {U = u} = record (образец соответствия)

  • Обновление: {record with U = u} (скобка-нотация)

Но вы не получаете функции первого класса бесплатно, если хотите, вы можете запрограммировать их вручную.

Ниже то, что я бы лично использовать в качестве конвенции:

static member New с кэрри аргументами для записи строительства.

Для обновления и деконструкции я бы использовал некоторую абстракцию Lenses.

Вот пример кода, который я бы добавить вручную:

// Somewhere as a top level definition or in a base library 
type Lens<'T,'U> = {Get: 'T -> 'U; Set: 'U -> 'T -> 'T } with 
    member l.Update f a = l.Set (f (l.Get a)) a 


type UV<'a> = {U : 'a; V : 'a } with 
// add these static members to your records 
    static member New u v : UV<'a> = {U = u; V = v} 
    static member u = {Get = (fun (x: UV<'a>) -> x.U); Set = fun t x -> {x with U = t}} 
    static member v = {Get = (fun (x: UV<'a>) -> x.V); Set = fun t x -> {x with V = t}} 


let uvRecord = UV.New 10 20 
let u   = UV.u.Get uvRecord 
let uvRecord1 = UV.u.Set (u+1) uvRecord 
let uvRecord2 = UV.u.Update ((+)1) uvRecord 

Таким образом, я бы первые функции класса для строительства, деконструкции, но и для обновления плюс другие очень интересные Линзы свойства, как вы можете read in this post.

UPDATE (в ответ на ваши комментарии)

Конечно, они могут быть определены позже, что это меняет? То же самое относится к конструктору New, его можно определить позже, но на самом деле это хорошо. Определяемые вами функции доступа также могут быть определены позже, и в любом случае может быть определено любое значение первоклассного коэффициента получения, настройки или обновления.

В любом случае, ответ на ваш вопрос: «нет, нет никаких соглашений», остальное это личное решение, которое было бы моим решением, а также многие Haskellers настаивают на получении каких-либо автоматических линз для записей Haskell.

Почему я решил пойти этим путем? Поскольку в терминах строк кода усилие добавления простой функции доступа почти такое же, как добавление get-Lens, поэтому по той же цене я получаю больше функциональности.

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

Возможно, я неправильно понял ваш вопрос, для меня ваш вопрос касался того, какое соглашение обычно используется для добавления первоклассных конструкторов, значений getters и seters для записей.

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

+0

В то время как объективы великолепны для композиции, я не совсем понимаю вас в преимуществах их реализации, когда они определяют структуру данных. Поскольку ваш [link] (http://bugsquash.blogspot.fr/2011/11/lenses-in-f.html) демонстрирует посредством методов расширения, , они также могут быть представлены ретроспективно. Мотивация для этого вопроса заключалась в стремлении избежать рефакторинга определений записей, а не лаконичности и удобочитаемости. Как линзы помогут мне в этом, если бы вы все равно могли набить их? – kaefer

+0

@kaefer Я ответил вам в обновлении. – Gustavo

Смежные вопросы