rudymatela / leancheck

enumerative property-based testing for Haskell
https://hackage.haskell.org/package/leancheck
Other
52 stars 8 forks source link

Define `resultsWithErrors` and such, with `Either String ()` rather than mere `Bool`. #18

Closed strake closed 2 years ago

rudymatela commented 2 years ago

Thanks for the proposed addition. I am not sure if this use case is frequent enough to warrant it being on the tool.

When it is needed, gathering errors can be replicated without changing the tool itself with the following short "plug-in" module:

module Errorable where

import Test.LeanCheck

data MaybeError = Ok | Error String deriving Show

class Errorable a where
  tierrors :: a -> [[([String], MaybeError)]]

instance Errorable MaybeError where
  tierrors merr = [[([],merr)]]

instance (Errorable b, Show a, Listable a) => Errorable (a->b) where
  tierrors perr  =  concatMapT tierrorsFor tiers
    where
    tierrorsFor x  =  mapFst (showsPrec 11 x "":) `mapT` tierrors (perr x)
    mapFst f (x,y)  =  (f x, y)

resultsWithErrors :: Errorable a => a -> [([String], MaybeError)]
resultsWithErrors = concat . tierrors

... then used with the following code:

import Errorable

error_prop_not_3 :: Int -> MaybeError
error_prop_not_3 3 = Error "it's three!"
error_prop_not_3 _ = Ok 

main :: IO ()                          
main = putStrLn $ unlines $ map show $ take 10 $ resultsWithErrors error_prop_not_3

to arrive at:

(["0"],Ok)
(["1"],Ok)
(["(-1)"],Ok)
(["2"],Ok)
(["(-2)"],Ok)
(["3"],Error "it's three!")
(["(-3)"],Ok)
(["4"],Ok)
(["(-4)"],Ok)
(["5"],Ok)

Whenever one needs a custom Testable instance, declaring a separate Somethingable instance is a very flexible and relatively easy solution.