{-# OPTIONS_GHC -fno-warn-orphans #-} module Data.GenValidity.Tree where import Data.GenValidity import Data.List.NonEmpty (NonEmpty (..)) import qualified Data.List.NonEmpty as NE import Data.Tree import Data.Validity.Tree () import Test.QuickCheck instance GenValid a => GenValid (Tree a) where genValid = genTreeOf genValid shrinkValid (Node v ts) = [Node v' ts' | (v', ts') <- shrinkValid (v, ts)] -- | Generate a tree of values that are generated as specified. -- -- This takes the size parameter much better into account genTreeOf :: Gen a -> Gen (Tree a) genTreeOf func = do ne <- genNonEmptyOf func turnIntoTree ne where turnIntoTree :: NonEmpty a -> Gen (Tree a) turnIntoTree (e :| es) = do groups <- turnIntoGroups es subtrees <- mapM turnIntoTree groups pure (Node e subtrees) turnIntoGroups :: [a] -> Gen [NonEmpty a] turnIntoGroups = go [] where go :: [a] -> [a] -> Gen [NonEmpty a] go acc [] = case NE.nonEmpty acc of Nothing -> pure [] Just ne -> pure [ne] go acc (e : es) = frequency [ ( 1, do rest <- go [] es pure ((e :| acc) : rest) ), (4, go (e : acc) es) ]