I'm new to Haskell. I'm playing with QuickCheck tests, trying to test a simple function calculateStrengthSingle
(see the source of testee below)
# Fighter.hs
module Fighter
( Quantity(Quantity)
, Fighter(TeamPlayer, LoneWolf, Polymorph)
, Strength(Strength)
, calculateStrengthSingle)
where
import System.Random
data Strength = Strength Double
instance Eq Strength where
Strength s1 == Strength s2 =
s1 == s2
instance Ord Strength where
Strength s1 < Strength s2 =
s1 < s2
data Quantity = Quantity Int deriving (Show)
instance Random Quantity where
randomR (Quantity lo, Quantity hi) g =
let rand = randomR (lo, hi) g
(r, g1) = rand
in (Quantity r, g1)
random g =
let rand = random g
(r, g1) = rand
in (Quantity r, g1)
data Fighter = TeamPlayer
| LoneWolf
| Polymorph
deriving (Show)
calculateStrengthSingle :: Quantity -> Fighter -> Strength
calculateStrengthSingle (Quantity number) TeamPlayer =
Strength(log (fromIntegral number))
calculateStrengthSingle _ _ = Strength 0.0
The test looks like this
# TestFighter.hs
import qualified Test.QuickCheck as QuickCheck
import Fighter
prop_StrengthPositive quantity fighter =
Fighter.calculateStrengthSingle quantity fighter >= Strength 0.0
instance QuickCheck.Arbitrary Fighter.Fighter where
arbitrary = QuickCheck.oneof([return Fighter.TeamPlayer, return Fighter.LoneWolf, return Fighter.Polymorph])
instance QuickCheck.Arbitrary Fighter.Quantity where
arbitrary = QuickCheck.choose(Fighter.Quantity 1, Fighter.Quantity 10)
main :: IO()
main = do
QuickCheck.quickCheck prop_StrengthPositive
When I do runhaskell TestFighter.hs
there's output (1 test)
(the number is changing, sometimes it's 0
other times it's 4
) and CPU is 100% loaded. Nothing happens for a minute or so. When I interrupt the program by Ctrl+C
, it spits out something like
^C*** Failed! Exception: 'user interrupt' (after 1 test):
Quantity 2
TeamPlayer
Questions:
You haven't defined the Ord
instance for Strength
correctly. You need to define <=
and not <
.
With only <
defined the function <=
enters into an infinite loop as it is defined in terms of compare
and compare
is defined in terms of <=
. Minimal definition needs to define either compare
or <=
.
Here is the fixed code for Ord
instance
instance Ord Strength where
Strength s1 <= Strength s2 =
s1 <= s2