2016-03-05 37 views
1

我試圖訪問嵌套數據(Foo.yBar在下面的示例中),但解開Foo內部Bar想到的直接方法不起作用。但如何正確解開它?如何在`data`中正確解開'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 - 就像BarFoo需求展開第一:

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 

所以,我怎麼也嵌套的「解包」?

[編輯]

一小時後或兩個嘗試的事情了,我想出了這個,它的工作原理:

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

這是慣用的方式做到這一點?爲什麼不fn2fn3工作?

回答

3

功能FN2FN3不工作,因爲編譯器不知道你指的是(FOO),它記錄的字段。您必須按名稱引用記錄字段。

功能FN4是一個完美的精解(雖然你的命名是相當混亂,的getY實際返回構造函數中的包裹記錄,而不是Ÿ值)。

據我所知,fn5是最短的可能的解決方案。我個人比較喜歡的輔助功能(如在你的第四個例子):

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

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

OK,是有道理的:它不是由_position_,但_name_ - 剛纔點擊我,謝謝。因此,我的'getY'應該被稱爲'getFoo'或者按照你寫的方式寫。 FWIW,我不是在尋找最短的解決方案,而是我可以看到模式中的解構。現在,我怎樣才能從模式中直接得到'y'? – 0dB

+1

像這樣:fn7(Bar {x,foo = Foo {y}})= x + y –

+1

另請注意,{field}是{field:field}的語法糖。 –

相關問題