読者です 読者をやめる 読者になる 読者になる

IT練習ノート

IT関連で調べたこと(実際は嵌ったこと)を書いています。

Record syntaxを使うときに設定しておくと便利な言語拡張

Record syntax を使うときに設定しておくと便利な言語拡張

DuplicateRecordFields

フィールド名の重複を許す。ただし、曖昧になる場合はエラーになる。

Prelude> :set -XDuplicateRecordFields
Prelude> data Foo = Foo {x :: Int}
Prelude> data Bar = Bar {x :: Char}
Prelude> :t Foo
Foo :: Int -> Foo
Prelude> :t Bar
Bar :: Char -> Bar

-- ambiguous

Prelude> :t x

<interactive>:1:1: error:
    Ambiguous occurrence ‘x’
    It could refer to either the field ‘x’,
                             defined at <interactive>:2:17
                          or the field ‘x’, defined at <interactive>:3:17
Prelude> let f = Foo {x=1}
Prelude> let b = Bar {x='a'}

-- function application

Prelude> x f

<interactive>:10:1: error:
    Ambiguous occurrence ‘x’
    It could refer to either the field ‘x’,
                             defined at <interactive>:2:17
                          or the field ‘x’, defined at <interactive>:3:17
Prelude> let z = x f :: Int

<interactive>:12:9: error:
    Ambiguous occurrence ‘x’
    It could refer to either the field ‘x’,
                             defined at <interactive>:2:17
                          or the field ‘x’, defined at <interactive>:3:17
Prelude> x (f :: Foo)
1
Prelude> x (b :: Bar)
'a'
Prelude>
Prelude> (\(Foo {x=t}) -> print t) f
1
Prelude> (\(Bar {x=t}) -> print t) b
'a'
Prelude>

-- record update

Prelude> f' = f {x=2}

<interactive>:23:6: error:
    • Record update is ambiguous, and requires a type signature
    • In the expression: f {x = 2}
      In an equation for ‘f'’: f' = f {x = 2}
Prelude> let f' = f {x=2} :: Foo
Prelude> :t f'
f' :: Foo
Prelude> x (f' :: Foo)
2
Prelude>

NamedFieldPuns

フィールド名の省略

Prelude> :set -XNamedFieldPuns
Prelude> data Buzz = Buzz { a :: Int ,b :: Char} deriving Show
Prelude> data Buzz = Buzz { a :: Integer ,b :: Char} deriving Show
Prelude> Buzz 11 'x'
Buzz {a = 11, b = 'x'}
Prelude> (\Buzz {a,b} -> print $ (show a) ++ " " ++ (show b) ) $ Buzz 11 'x'
"11 'x'"

RecordWildCards

フィールド名のワイルドカード。これを指定しておけばNameFieldPunsは不要そうな感じ。

Prelude> :set -XRecordWildCards
Prelude> (\Buzz {..} -> print $ (show a) ++ " " ++ (show b) ) $ Buzz 11 'x'
"11 'x'"