haskell-numerics / random-fu

A suite of Haskell libraries for representing, manipulating, and sampling random variables
42 stars 21 forks source link

Constraint solving broken in GHC 9 due to Template Haskell splices #75

Closed funketh closed 2 years ago

funketh commented 3 years ago

I think the TH used to generate instances for integral and float types is broken for the newest TH version:

random-fu             > [ 7 of 30] Compiling Data.Random.Distribution.Uniform
random-fu             >  
random-fu             > /home/theo/prj/random-fu/random-fu/src/Data/Random/Distribution/Uniform.hs:136:10: error:
random-fu             >     • Could not deduce (Distribution Uniform Integer)
random-fu             >         arising from a use of ‘uniformT’
random-fu             >       from the context: RealFloat a
random-fu             >         bound by the type signature for:
random-fu             >                    realFloatStdUniform :: forall a (m :: * -> *).
random-fu             >                                           RealFloat a =>
random-fu             >                                           RVarT m a
random-fu             >         at src/Data/Random/Distribution/Uniform.hs:132:1-47
random-fu             >     • In a stmt of a 'do' block: x <- uniformT 0 (b - 1)
random-fu             >       In the expression:
random-fu             >         do let (b, e) = decodeFloat one
random-fu             >            x <- uniformT 0 (b - 1)
random-fu             >            if x == 0 then
random-fu             >                return (0 `asTypeOf` one)
random-fu             >            else
random-fu             >                return (encodeFloat x e)
random-fu             >       In an equation for ‘realFloatStdUniform’:
random-fu             >           realFloatStdUniform
random-fu             >             = do let (b, e) = ...
random-fu             >                  x <- uniformT 0 (b - 1)
random-fu             >                  if x == 0 then
random-fu             >                      return (0 `asTypeOf` one)
random-fu             >                  else
random-fu             >                      return (encodeFloat x e)
random-fu             >             where
random-fu             >                 one = 1
random-fu             >     |
random-fu             > 136 |     x <- uniformT 0 (b-1)
random-fu             >     |          ^^^^^^^^^^^^^^^^
random-fu             >  
random-fu             > /home/theo/prj/random-fu/random-fu/src/Data/Random/Distribution/Uniform.hs:150:18: error:
random-fu             >     • Could not deduce (Distribution Uniform Integer)
random-fu             >         arising from a use of ‘uniformT’
random-fu             >       from the context: HasResolution r
random-fu             >         bound by the type signature for:
random-fu             >                    fixedStdUniform :: forall r (m :: * -> *).
random-fu             >                                       HasResolution r =>
random-fu             >                                       RVarT m (Fixed r)
random-fu             >         at src/Data/Random/Distribution/Uniform.hs:145:1-55
random-fu             >     • In a stmt of a 'do' block: u <- uniformT 0 (res)
random-fu             >       In the expression:
random-fu             >         do u <- uniformT 0 (res)
random-fu             >            return (mkFixed u)
random-fu             >       In an equation for ‘x’:
random-fu             >           x = do u <- uniformT 0 (res)
random-fu             >                  return (mkFixed u)
random-fu             >     |
random-fu             > 150 |             u <- uniformT 0 (res)
random-fu             >     |                  ^^^^^^^^^^^^^^^^
random-fu             >  
random-fu             > /home/theo/prj/random-fu/random-fu/src/Data/Random/Distribution/Uniform.hs:242:1: error:
random-fu             >     • No instance for (Distribution StdUniform Double) for ‘stdUniform’
random-fu             >     • In the pragma: {-# SPECIALIZE stdUniform :: RVar Double #-}
random-fu             >     |
random-fu             > 242 | {-# SPECIALIZE stdUniform :: RVar Double #-}
random-fu             >     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
random-fu             >  
random-fu             > /home/theo/prj/random-fu/random-fu/src/Data/Random/Distribution/Uniform.hs:243:1: error:
random-fu             >     • No instance for (Distribution StdUniform Float) for ‘stdUniform’
random-fu             >     • In the pragma: {-# SPECIALIZE stdUniform :: RVar Float #-}
random-fu             >     |
random-fu             > 243 | {-# SPECIALIZE stdUniform :: RVar Float #-}
random-fu             >     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
random-fu             >  
random-fu             > /home/theo/prj/random-fu/random-fu/src/Data/Random/Distribution/Uniform.hs:251:1: error:
random-fu             >     • No instance for (Distribution StdUniform Double)
random-fu             >         for ‘stdUniformT’
random-fu             >     • In the pragma: {-# SPECIALIZE stdUniformT :: RVarT m Double #-}
random-fu             >     |
random-fu             > 251 | {-# SPECIALIZE stdUniformT :: RVarT m Double #-}
random-fu             >     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
random-fu             >  
random-fu             > /home/theo/prj/random-fu/random-fu/src/Data/Random/Distribution/Uniform.hs:252:1: error:
random-fu             >     • No instance for (Distribution StdUniform Float) for ‘stdUniformT’
random-fu             >     • In the pragma: {-# SPECIALIZE stdUniformT :: RVarT m Float #-}
random-fu             >     |
random-fu             > 252 | {-# SPECIALIZE stdUniformT :: RVarT m Float #-}
random-fu             >     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

stack.yaml used:

resolver: nightly-2021-05-01
compiler: ghc-9.0.1

packages:
- random-fu
- random-source
- rvar
- tests/speed

extra-deps:
- flexible-defaults-0.0.3
- ghc-boot-th-9.0.1
- mwc-random-0.15.0.1
- MonadRandom-0.5.3
- random-1.2.0
- splitmix-0.1.0.3
- syb-0.7.2.1
- template-haskell-2.17.0.0
- th-abstraction-0.4.2.0
  # GHC 9 patch
- github: mokus0/th-extras
  commit: 57a97b4df128eb7b360e8ab9c5759392de8d1659
funketh commented 3 years ago

This is a GHC 9 change: https://downloads.haskell.org/ghc/9.0.1/docs/html/users_guide/9.0.1-notes.html

Breaking change: Template Haskell splices now act as separation points between constraint solving passes. It is no longer possible to use an instance of a class before a splice and define that instance after a splice. For example, this code now reports a missing instance for C Bool:

class C a where foo :: a
bar :: Bool
bar = foo
$(return [])
instance C Bool where foo = True
funketh commented 3 years ago

So the only two options I can think of are:

funketh commented 3 years ago

okay so the first approach doesn't really work as some instances require functions which require instances themselves... this whole situation is really unfortunate, I dislike using cyclic modules for this but I don't see an alternative?

funketh commented 3 years ago

we could just expand the TH manually... maybe using DerivingVia and StandaloneDeriving will help shorten this a bit