polytropos-quickcheck
Copyright(c) 2026 The Polytropos Authors
LicenseEUPL-1.2 OR Apache-2.0
Maintainernadia.yvette.chambers@ik.me
Stabilityexperimental
Portabilitynon-portable (GHC extensions)
Safe HaskellNone
LanguageGHC2021

Polytropos.QuickCheck

Description

Integrates polytropos open records and variants with QuickCheck property-based testing.

Architectural Overview & Rationale

Records

'Arbitrary (Record r)' generates each field value via that field's own Arbitrary instance (the walk is heterogeneous: rows may freely mix field types) and packs the results straight into the contiguous SmallArray payload — with no intermediate tuples or generic-representation trees.

Shrinking is slot-indexed: each field slot is shrunk independently, one field at a time, so shrinking a \(k\)-field record yields \(O(k)\) candidates per level instead of the full Cartesian product over per-field shrink lists.

Variants

'Arbitrary (Variant s)' uniformly selects a constructor tag index and generates that constructor's payload fields. Shrinking is branch-preserving: only the payload of the currently active constructor is shrunk; the tag never changes, so a counterexample stays on the constructor branch that triggered the property failure.

When to Use This Module

  • When property-testing systems that use polytropos open records and variants.
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE TypeApplications #-}

import Test.QuickCheck
import Polytropos
import Polytropos.QuickCheck

type User = Record '["id" ':= Int, "active" ':= Bool]

prop_userPositiveId :: Property
prop_userPositiveId = forAll (arbitrary @User) $ \u ->
  u.id == u.id
Synopsis

Row and Sum Constraint Walks

class AllArbitrary (r :: Row) where Source #

Heterogeneous generation walk: every field of the row r has an Arbitrary instance at its own type.

Methods

genFields :: Proxy r -> Gen [Identity (Any :: Type)] Source #

Generate a value for each payload slot, in row order.

shrinkFields :: Proxy r -> [Identity (Any :: Type)] -> [[Identity (Any :: Type)]] Source #

Slot-indexed shrinks of the payload: one field shrinks at a time.

Instances

Instances details
AllArbitrary ('[] :: [Pair Symbol Type]) Source # 
Instance details

Defined in Polytropos.QuickCheck

Methods

genFields :: Proxy ('[] :: [Pair Symbol Type]) -> Gen [Identity (Any :: Type)] Source #

shrinkFields :: Proxy ('[] :: [Pair Symbol Type]) -> [Identity (Any :: Type)] -> [[Identity (Any :: Type)]] Source #

(Arbitrary a, AllArbitrary r) => AllArbitrary ((n ':= a) ': r) Source # 
Instance details

Defined in Polytropos.QuickCheck

Methods

genFields :: Proxy ((n ':= a) ': r) -> Gen [Identity (Any :: Type)] Source #

shrinkFields :: Proxy ((n ':= a) ': r) -> [Identity (Any :: Type)] -> [[Identity (Any :: Type)]] Source #

class AllCtorsArbitrary (s :: SumRow) where Source #

Heterogeneous generation walk over a sum row: every constructor's field row satisfies AllArbitrary.

Methods

numCtors :: Proxy s -> Int Source #

Number of constructors in the sum.

genCtorFields :: Proxy s -> Int -> Gen [Identity (Any :: Type)] Source #

Generate the payload fields of constructor i (0-based).

shrinkCtorFields :: Proxy s -> Int -> [Identity (Any :: Type)] -> [[Identity (Any :: Type)]] Source #

Slot-indexed shrinks of the payload of constructor i.

Instances

Instances details
AllCtorsArbitrary ('[] :: [Pair Symbol Row]) Source # 
Instance details

Defined in Polytropos.QuickCheck

Methods

numCtors :: Proxy ('[] :: [Pair Symbol Row]) -> Int Source #

genCtorFields :: Proxy ('[] :: [Pair Symbol Row]) -> Int -> Gen [Identity (Any :: Type)] Source #

shrinkCtorFields :: Proxy ('[] :: [Pair Symbol Row]) -> Int -> [Identity (Any :: Type)] -> [[Identity (Any :: Type)]] Source #

(AllArbitrary fs, AllCtorsArbitrary s) => AllCtorsArbitrary ((c ':= fs) ': s) Source # 
Instance details

Defined in Polytropos.QuickCheck

Methods

numCtors :: Proxy ((c ':= fs) ': s) -> Int Source #

genCtorFields :: Proxy ((c ':= fs) ': s) -> Int -> Gen [Identity (Any :: Type)] Source #

shrinkCtorFields :: Proxy ((c ':= fs) ': s) -> Int -> [Identity (Any :: Type)] -> [[Identity (Any :: Type)]] Source #

Orphan instances

AllArbitrary r => Arbitrary (Record r) Source # 
Instance details

Methods

arbitrary :: Gen (Record r) #

shrink :: Record r -> [Record r] #

AllCtorsArbitrary s => Arbitrary (Variant s) Source # 
Instance details

Methods

arbitrary :: Gen (Variant s) #

shrink :: Variant s -> [Variant s] #