2

我正在尝试访问嵌套数据(在下面的示例中为Foo.yinside Bar),但是想到的直接展开Foo内部的方法Bar不起作用。但是如何正确解包呢?

这是我的数据:

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

这是惯用的方法吗?为什么不fn2工作fn3

4

1 回答 1

3

函数fn2fn3不起作用,因为编译器不知道您指的是哪个记录字段(foo)。您必须按名称引用记录字段。

函数fn4是一个完美的解决方案(尽管您的命名很混乱,但getY实际上返回Foo构造函数中的包装记录,而不是y值)。

据我所知,fn5是最短的解决方案。我个人更喜欢一个辅助函数(就像你的第四个例子一样):

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

fn6 :: Bar -> Int
fn6 (Bar { x, foo }) = x + getY foo
于 2016-03-05T18:45:10.117 回答