上下文
如果我将以下内容加载到支持RecordDotSyntax的ghc-9.2.1-alpha2中:
{-# 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
如果我添加以下内容作为别名和Ari建议:
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.
这里有两个问题。
-
您已启用
RebindableSyntax
。这允许您重新定义某些行为通过在本地范围中定义某些函数(否则从Prelude导入)。因此,RebindableSyntax
意味着NoImplicitPrelude
。您需要手动导入Prelude
,可以选择隐藏要覆盖的函数。import Prelude hiding (...)
-
您已经启用了
OverloadedRecordUpdate
,这是GHC9.2中的一个尚未稳定的实验功能。GHC用户指南的相关版本是这样说的:
此时,当OverloadedRecordUpdate为时,必须启用RebindableSyntax,并且要求用户提供getField和setField的定义。我们预计这一限制将在未来的GHC版本中取消,该版本内置对setField的支持。
默认的
getField
可以从GHC.Records
导入,但setField
当前不可用,因此您必须自己实现它。玩得开心!
编辑11/08:这个答案大部分不完整,部分不正确。看看我的另一个答案
正如@alias所解释的,如果启用RebindableSyntax
,前奏曲将不会自动加载。GHC.Records
也不会,它通常由记录语法扩展加载并需要。
您必须添加以下内容:
import Prelude
import GHC.GetRecords