Skip to content

Instantly share code, notes, and snippets.

@larskuhtz
Last active February 17, 2023 17:56
Show Gist options
  • Save larskuhtz/c216e2fd9e6aac580ea9640d554dddf8 to your computer and use it in GitHub Desktop.
Save larskuhtz/c216e2fd9e6aac580ea9640d554dddf8 to your computer and use it in GitHub Desktop.
Bug with the mod package And GHC 9.4.4 on Linux
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Main (main) where
import Data.Mod (Mod)
import GHC.TypeNats (KnownNat)
import Numeric.Natural (Natural)
import Test.QuickCheck (Arbitrary, arbitrary)
import Test.QuickCheck.Instances ()
newtype Fq = Fq (Mod 18446744073709551616 {- 2^64 -}) deriving (Num)
instance KnownNat n => Arbitrary (Mod n) where
arbitrary = fromIntegral <$> arbitrary @Natural
instance Arbitrary Fq where
arbitrary = Fq <$> arbitrary
main :: IO ()
main = let Fq x = -1 in print x
cabal-version: 3.0
name: mod-bug
version: 0.1.0.0
synopsis: demonstrate bug when using mod package
executable bug
main-is: Main.hs
hs-source-dirs: .
default-language: Haskell2010
build-depends:
, base ==4.17.0.0
, mod ==0.2.0.1
, QuickCheck ==2.14.2
, quickcheck-instances ==0.3.28
@larskuhtz
Copy link
Author

larskuhtz commented Feb 17, 2023

With optimization enabled (-O1 or -O2) this program prints

0

which is wrong. Without optimization or with ghci it prints the correct result:

18446744073709551615

@larskuhtz
Copy link
Author

The behavior is actually somewhat non-deterministic, at least on MacOS. Some builds give the correct result and some builds give the wrong result. On Linux the wrong result is produced more consistently.

@larskuhtz
Copy link
Author

I haven't yet been able to find a minimal example that doesn't include the QuickCheck instances. In a larger production system the bug was observed on a code base without these instances.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment