Haskell 在不同 GHC 版本中的多态函数

问题描述 投票:0回答:1

我正在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
有什么不同吗?

haskell ghc
1个回答
0
投票

是的,不久前我在尝试遵循一些 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

并且不会生成警告,因为这是构造函数调用的一部分,而不是记录更新。

© www.soinside.com 2019 - 2024. All rights reserved.