2016-03-05 6 views
1

Я пытаюсь получить доступ к вложенным данным (внутри Bar в примере ниже), но простые подходы к разворачиванию Foo внутри Bar, которые приходят на ум, не работают. Но как развернуть его правильно?Как правильно разворачивать `данные` внутри` data`?

Вот мои данные:

module Foo where 

import Prelude 

data Foo = Foo { y :: Int } 

data Bar = Bar { x :: Int 
       , foo :: Foo } 

Следующая (конечно) не компилируется, ошибка Could not match type { y :: Int } with type Foo - так же, как Bar, Foo потребности разворачивая первый:

fn1 :: Bar -> Int 
fn1 (Bar { x, foo }) = x + foo.y 

Так что я положил мой надеется на следующее, но, увы, компилятор говорит «нет» (круглые скобки вокруг Foo конструктор не помогает):

fn2 :: Bar -> Int 
fn2 (Bar { x, Foo { y } }) = x + y 

fn3 :: Bar -> Int 
fn3 (Bar { x, Foo f }) = x + f.y 

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

getY (Foo foo) = foo -- helper function 

fn4 :: Bar -> Int 
fn4 (Bar { x, foo }) = let foo2 = getY foo in 
         x + foo2.y 

Итак, как же я вложенный «разворачивать»?

[EDIT]

Через час или два в попытке вещи, я придумал это, который работает:

fn5 :: Bar -> Int 
fn5 (Bar { x, foo = (Foo f) }) = x + f.y 

Это идиоматических способ сделать это? Почему не работают fn2 и fn3?

ответ

3

Функция fn2 и FN3 не работает, потому что компилятор не знает, какую запись поля вы имеете в виду (обув). Вы должны указывать поля записи по имени.

Функция FN4 это прекрасно подходит (хотя ваше именование довольно запутанное, GetY фактически возвращает обернутую запись внутри Foo конструктора , а не у значения).

Насколько я могу судить, fn5 - это кратчайшее возможное решение. Я бы лично предпочел вспомогательную функцию (например, в вашем четвертом примере):

getY :: Foo -> Int 
getY (Foo rec) = rec.y 

fn6 :: Bar -> Int 
fn6 (Bar { x, foo }) = x + getY foo 
+0

ОК, имеет смысл: это не _position_, а _NAME_ - просто щелкнул для меня, спасибо. И таким образом мой 'getY' следует называть' getFoo' или писать так, как вы его написали. FWIW, я не искал кратчайшего решения, кроме одного, где я вижу разрушение в шаблоне. Теперь, как я могу получить «y» прямо из шаблона? – 0dB

+1

Нравится это: fn7 (Bar {x, foo = Foo {y}}) = x + y –

+1

Также обратите внимание, что {поле} является синтаксическим сахаром для {field: field}. –