我正在MacOS(M2 gpu)中的haskell中开发vulkan应用程序。
以下项目中的代码
width = realToFrac (width (swapchainExtent :: Extent2D))
(vulkan
)
https://github.com/expipiplus1/vulkan/blob/2007a6ebca9a585028163a850bcedef856fc1e94/examples/sdl-triangle/Main.hs#L283C66-L283C74
在
ghc 8.10.7
编译成功。ghc 9.6.3
有错误。/Users/liuzichao/Hulkan/test/Main.hs:283:40: error:
Ambiguous occurrence ‘width’
It could refer to
either the field ‘width’ of record ‘Viewport’,
imported from ‘Vulkan.Core10’ at test/Main.hs:36:1-30
(and originally defined in ‘Vulkan.Core10.Pipeline’)
or the field ‘width’ of record ‘FramebufferCreateInfo’,
imported from ‘Vulkan.Core10’ at test/Main.hs:36:1-30
(and originally defined in ‘Vulkan.Core10.Pass’)
or the field ‘width’ of record ‘Extent3D’,
imported from ‘Vulkan.Core10’ at test/Main.hs:36:1-30
(and originally defined in ‘Vulkan.Core10.FundamentalTypes’)
or the field ‘width’ of record ‘Extent2D’,
imported from ‘Vulkan.Core10’ at test/Main.hs:36:1-30
(and originally defined in ‘Vulkan.Core10.FundamentalTypes’)
|
283 | , width = realToFrac (width (swapchainExtent :: Extent2D))
|
为什么会发生这种情况?如果
ghc 9.6.3
与 ghc 8.10.7
有什么不同吗?
是的,不久前我在尝试遵循一些 Vulkan 示例时遇到了同样的问题。
基于此提案正在对记录字段进行许多更改,这些更改要求不明确的字段名称大大不那么模糊。我发现 GHC 更改日志中的文档不完整且令人困惑,但该提案的 which 部分正在与 which 版本的 GHC 一起推出。
但是,GHC 8.10.7 接受以下程序:
{-# LANGUAGE DuplicateRecordFields #-}
module Field where
data Rect = Rect { width :: Int, height :: Int }
data Circle = Cirlce { width :: Int }
biggerRect :: Rect -> Rect
biggerRect r = r { width = 2 * width (r :: Rect) }
编译但在 GHC 9.2.1 中抛出一些警告(与使用更新语法
width = ...
而不是 width (r :: Rect)
访问有关),并被 9.4.1 彻底拒绝:
Field.hs:9:32: error:
Ambiguous occurrence ‘width’
It could refer to
either the field ‘width’ of record ‘Circle’,
defined at Field.hs:6:24
or the field ‘width’ of record ‘Rect’, defined at Field.hs:5:20
|
9 | biggerRect r = r { width = 2 * width (r :: Rect) }
| ^^^^^
最简单的修复方法是使用
OverloadedRecordDot
扩展(自 GHC 9.2.0 起可用),它可以让你编写:
{-# LANGUAGE OverloadedRecordDot #-}
biggerRect :: Rect -> Rect
biggerRect r = r { width = 2 * r.width }
这仍然会在
width = ...
更新部分引发警告,但它可以编译。
对于上面的示例,可以执行以下操作:
, width = realToFrac swapChainExtent.width
并且不会生成警告,因为这是构造函数调用的一部分,而不是记录更新。