使用 RecordDotSyntax 更新记录会导致错误

Updating a record using RecordDotSyntax results in an error

上下文

如果我将以下内容加载到 ghc-9.2.1-alpha2 which has support for RecordDotSyntax 中:

{-# LANGUAGE OverloadedRecordDot, OverloadedRecordUpdate, DuplicateRecordFields #-}
----------------------------------------------------------------------
data Point = Point { x :: Double, y :: Double }

instance Show Point where
    show p = "Point { x = " ++ show p.x ++ ", y = " ++ show p.y ++ " }"

p = Point 10 20

然后我可以 运行 在 ghci 中执行以下操作:

ghci> p { x = 30 }
Point { x = 30.0, y = 20.0 }

太棒了,开始工作了!

问题

但是,如果我将以下内容添加到上面的测试文件中:

result =
    let
        a = Point 1 2
        b = a { x = 3 }
    in
        b

然后重新加载,我收到以下消息:

ghci> :r
[1 of 1] Compiling Main             ( /home/dharmatech/tmp/test-ghc-9.2.0.20210422/point-update-issue.hs, interpreted )

/home/dharmatech/tmp/test-ghc-9.2.0.20210422/point-update-issue.hs:13:13: error:
    RebindableSyntax is required if OverloadedRecordUpdate is enabled.
   |
13 |         b = a { x = 3 }
   |             ^^^^^^^^^^^
Failed, no modules loaded.

我试过的

如果我按照消息的建议添加 RebindableSyntax,我会收到更多错误,如下所示:

/home/dharmatech/tmp/test-ghc-9.2.0.20210422/point-update-issue.hs:3:27: error:
    Not in scope: type constructor or class ‘Double’
  |
3 | data Point = Point { x :: Double, y :: Double }
  |

问题

有没有办法让它工作?还是尚未实施?

2021-08-10更新

如果我将以下内容添加为 aliasAri 建议:

import Prelude
import GHC.Records

我得到以下信息:

point-update-issue.hs:17:13: error:
    Not in scope: ‘setField’
    Perhaps you meant ‘getField’ (imported from GHC.Records)
   |
17 |         b = a { x = 3 }
   |             ^^^^^^^^^^^
Failed, no modules loaded.

编辑 11/08:此答案大部分不完整且部分不正确。看我的另一个回答。

如@alias 所述,如果启用 RebindableSyntax,Prelude 将不会自动加载。 GHC.Records 也不会,通常由记录语法扩展加载和要求。

您必须添加:

import Prelude
import GHC.GetRecords

这里有两个问题。

  1. 您已启用 RebindableSyntax。这允许您重新定义某些行为 通过在本地范围内定义某些函数,否则从 Prelude 导入。因此,RebindableSyntax 意味着 NoImplicitPrelude。您需要手动导入 Prelude,可选择隐藏要覆盖的函数。

    import Prelude hiding (...)
    
  2. 您启用了 OverloadedRecordUpdate,这是 GHC 9.2 中尚未稳定的实验性功能。

    GHC User's Guide的相关版本是这样说的:

    At this time, RebindableSyntax must be enabled when OverloadedRecordUpdate is and users are required to provide definitions for getField and setField. We anticipate this restriction to be lifted in a future release of GHC with builtin support for setField.

    默认的getField可以从GHC.Records导入,但是setField目前还没有,所以要自己实现。

    玩得开心!