Reputation: 84
I was reading the Haskellbook and trying to test Monoid laws for a Monoid instance for a simple Bool
like data type using the checkers library. But when I try to load the code in ghci
, I get the following error:
BadMonoid.hs:21:20: error:
• No instance for (QuickCheck-2.14:Test.QuickCheck.Arbitrary.Arbitrary
Bull)
arising from a use of ‘monoid’
• In the first argument of ‘quickBatch’, namely ‘(monoid Twoo)’
In the expression: quickBatch (monoid Twoo)
In an equation for ‘main’: main = quickBatch (monoid Twoo)
|
21 | main = quickBatch (monoid Twoo)
| ^^^^^^^^^^^
Failed, no modules loaded.
Though, I have defined an Arbitrary
instance for my data type Bull
. I have searched on the Internet and Stack Overflow and found a related post. I have tried the solution given there(using GHC.Generics
) but it results in the same error.
Here is the code:
module BadMonoid where
import Data.Monoid
import Test.QuickCheck
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes
data Bull = Fools | Twoo deriving (Eq, Show)
instance Arbitrary Bull where
arbitrary = frequency [(1, return Fools), (1, return Twoo)]
instance Monoid Bull where
mempty = Fools
instance Semigroup Bull where
(<>) _ _ = Fools
instance EqProp Bull where (=-=) = eq
main :: IO ()
main = quickBatch (monoid Twoo)
Upvotes: 2
Views: 206
Reputation: 14676
The issue is that there are two incompatible versions of QuickCheck installed. We can tell from the error message, as it mentions the version (QuickCheck-2.14
) in the type:
• No instance for (QuickCheck-2.14:Test.QuickCheck.Arbitrary.Arbitrary
Bull)
As Daniel mentioned, the solution is to create a Cabal project that depends on QuickCheck
and checkers
, and use Cabal commands (e.g. cabal repl
) instead of GHC directly.
By default, GHC can see every version of every package that's installed on the machine. But it doesn't know how to choose between them. If run on its own, it will pick whatever package versions it finds first – which may not consistent with each other.
Enter Cabal. The primary feature of Cabal is its solver: it can select a consistent set of packages, and tell GHC to only use those packages. That's why creating a Cabal project fixes the issue.
In general, it is an antipattern to run cabal install --lib
. (Installing executables is okay, as they're self-contained.) If you need to install libraries from Hackage, create a Cabal project which depends on the library.
Upvotes: 3