Foo.y
ネストされたデータ (以下の例の内部)にアクセスしようとしていますが、頭に浮かぶ内部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
— のよう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
では、ネストされた「アンラップ」を行うにはどうすればよいでしょうか?
[編集]
1〜2時間試してみた後、これを思いつきました。これはうまくいきます:
fn5 :: Bar -> Int
fn5 (Bar { x, foo = (Foo f) }) = x + f.y
これは慣用的な方法ですか?なぜ仕事をしないfn2
のfn3
ですか?