haskellhmatrix

possible regression? type error compiling using ghc 9.6.2, hmatrix 0.20.2, and Vector 0.13.0.0


Compiling the following code using ghc 9.6.2, hmatrix 0.20.2, and Vector 0.13.0.0

import Numeric.LinearAlgebra

import qualified Data.Vector.Storable as V

nnz :: Vector R -> Int
nnz v = size $ V.filter (/= 0) v

avg :: Vector R -> R
avg v = V.sum v / fromIntegral (size v)

gets the following errors:

 ghc hvBug.hs
Loaded package environment from /Users/gcolpitts/.ghc/x86_64-darwin-9.6.2/environments/default
[1 of 2] Compiling Main             ( hvBug.hs, hvBug.o )

hvBug.hs:6:32: error: [GHC-83865]
    • Couldn't match expected type: V.Vector t0
                  with actual type: Vector R
      NB: ‘V.Vector’
            is defined in ‘Data.Vector.Storable’ in package ‘vector-0.13.0.0’
          ‘Vector’
            is defined in ‘Data.Vector.Storable’ in package ‘vector-0.13.0.0’
    • In the second argument of ‘V.filter’, namely ‘v’
      In the second argument of ‘($)’, namely ‘V.filter (/= 0) v’
      In the expression: size $ V.filter (/= 0) v
  |
6 | nnz v = size $ V.filter (/= 0) v
  |                                ^

hvBug.hs:9:15: error: [GHC-83865]
    • Couldn't match expected type: V.Vector R
                  with actual type: Vector R
      NB: ‘V.Vector’
            is defined in ‘Data.Vector.Storable’ in package ‘vector-0.13.0.0’
          ‘Vector’
            is defined in ‘Data.Vector.Storable’ in package ‘vector-0.13.0.0’
    • In the first argument of ‘V.sum’, namely ‘v’
      In the first argument of ‘(/)’, namely ‘V.sum v’
      In the expression: V.sum v / fromIntegral (size v)
  |
9 | avg v = V.sum v / fromIntegral (size v)
  |               ^

Note that https://dis.um.es/~alberto/hmatrix/hmatrixtut.html#types says:

We can also import qualified Data.Storable.Vector as V to use any desired function from the vector package.

I believe this code used to compile and thus that it may be a regression in ghc 9.6.2, hmatrix 0.20.2, or Vector 0.13.0.0

At https://hackage.haskell.org/package/vector-0.13.0.0/changelog I see:

One consequence of this choice is that it is no longer possible to coerce between Storable.Vector a and Storable.Vector b if a and b are nominally distinct but representationally equal types. We now provide unsafeCoerce{M}Vector and unsafeCast functions to allow this (the onus is on the user to ensure that no Storable invariants are broken when using these functions).

Is it possible that this is the cause of the error? If so how do I change the code so that it compiles?


Solution

  • I was able to compile your example with Stack nightly-2023-09-09 using the same GHC, hmatrix, and vector packages as you, so I believe this is a problem with your globally installed hmatrix and vector packages.

    One clue is this part of the error message:

    • Couldn't match expected type: V.Vector t0
                  with actual type: Vector R
      NB: ‘V.Vector’
            is defined in ‘Data.Vector.Storable’ in package ‘vector-0.13.0.0’
          ‘Vector’
            is defined in ‘Data.Vector.Storable’ in package ‘vector-0.13.0.0’
    

    It is not normal for GHC to refer to the same identifier in the same package with two different qualified names, or a qualified name plus an unqualified name, as has happened here.

    What has probably happened is that your hmatrix package was built and installed against one build of vector-0.13.0.0, and then vector-0.13.0.0 was rebuilt. Even though these packages have the same name and version, they are not recognized as the same package, and the qualified name V.Vector imported from Data.Vector.Storable and the unqualified Vector imported from Numeric.LinearAlgebra are not recognized as referring to the same type.

    Assuming you're trying to use Cabal to globally install packages, I'd suggest running:

    cabal install --reinstall --lib vector-0.13.0.0
    cabal install --reinstall --lib hmatrix-0.20.2
    

    and then try recompiling your program.

    (Actually, I'm a little worried this won't work. In my testing, cabal seemed to ignore the --reinstall flag.)