haskellghc

Haskell's polymorphic functions in different GHC version


I am developping vulkan app in haskell in MacOS (M2 gpu).

Code width = realToFrac (width (swapchainExtent :: Extent2D)) in following project (vulkan) https://github.com/expipiplus1/vulkan/blob/2007a6ebca9a585028163a850bcedef856fc1e94/examples/sdl-triangle/Main.hs#L283C66-L283C74

Compiled success in ghc 8.10.7.
But error in ghc 9.6.3.
The error message is

/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))
    |               

Why this happend? If ghc 9.6.3 has something different with ghc 8.10.7?


Solution

  • Yes, I ran into this same problem trying to follow some Vulkan examples a while back.

    A number of changes are being made to record fields based on this proposal which require ambiguous field names to be much less ambiguous. I've found the documentation in the GHC change logs incomplete and confusing as regards which parts of this proposal are being rolled out with which versions of GHC, though.

    However, the following program is accepted by 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) }
    

    compiles but throws some warnings in GHC 9.2.1 (related to the use of the update syntax width = ... rather than the width (r :: Rect) access), and is rejected outright by 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) }
      |                                ^^^^^
    

    The easiest fix is to use the OverloadedRecordDot extension (available since GHC 9.2.0), which lets you write:

    {-# LANGUAGE OverloadedRecordDot #-}
    
    biggerRect :: Rect -> Rect
    biggerRect r = r { width = 2 * r.width }
    

    This still throws a warning on the width = ... update part, but it compiles.

    For your example above, the following works:

    , width    = realToFrac swapChainExtent.width
    

    and generates no warnings, since this is part of a constructor call, not a record update.