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

北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

ghci 7.10 と 8.0 のレコード記法の違い

DuplicateRecordFields を実装した影響だと思うけど、 ghci で重複するレコード名を定義したときの振る舞いが 7.10 と 8.0 で違ってる。

まず 7.10 。「フィールド定義が消される」という振る舞いに見える。

$ stack --resolver ghc-7.10 ghci
Configuring GHCi with the following packages:
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
Prelude> data X = X { x :: Bool }
Prelude> data Y = Y { x :: Int }
Prelude> let anX = X { x = True }

<interactive>:18:11:
    Constructor ‘X’ does not have field ‘x’
    In the expression: X {x = True}
    In an equation for ‘anX’: anX = X {x = True}
Prelude> let anX = X { x = 10 }

<interactive>:19:11:
    Constructor ‘X’ does not have field ‘x’
    In the expression: X {x = 10}
    In an equation for ‘anX’: anX = X {x = 10}
Prelude> :t anX

<interactive>:1:1:
    Not in scope: ‘anX’
    Perhaps you meant one of these:
      ‘and’ (imported from Prelude), ‘any’ (imported from Prelude)

8.0 で同じことをやってみる。フィールドがないことを検知してないように思える。気持ち悪いのは、 True を渡すと値を生成できてしまうこと。しかも True はなかったことにされて x フィールドの値を評価すると例外が投げられる。

$ stack ghci
Configuring GHCi with the following packages:
GHCi, version 8.0.1: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from C:\tools\msys64\tmp\ghci1668\ghci-script
Prelude> data X = X { x :: Bool }
Prelude> data Y = Y { x :: Int }
Prelude> let anX = X { x = True }

<interactive>:67:11: warning: [-Wmissing-fields]
    • Fields of ‘X’ not initialised: x
    • In the expression: X {x = True}
      In an equation for ‘anX’: anX = X {x = True}
Prelude> let anX = X { x = 10 }

<interactive>:68:19: error:
    • No instance for (Num Bool) arising from the literal ‘10’
    • In the ‘x’ field of a record
      In the expression: X {x = 10}
      In an equation for ‘anX’: anX = X {x = 10}
Prelude> :t anX
anX :: X
Prelude> let (X x') = anX in x'
*** Exception: <interactive>:3:11-24: Missing field in record construction x

これが起こるのは REPL 上だけで、ソースコード上でフィールド名が重複していれば当然コンパイルが通らないので、大きな問題ではないだろう。そもそも 7.10 系の振る舞いが理想的かってのもある。バグな気はするけど。