{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Constrained.Spec.Tree (BinTree (..), TreeFn, rootLabel_, TreeSpec (..)) where
import Data.Kind
import Data.Tree
import GHC.Generics
import Test.QuickCheck (shrinkList)
import Constrained.Base
import Constrained.Core
import Constrained.GenT
import Constrained.List
import Constrained.Spec.Generics
import Constrained.Spec.Pairs
import Constrained.Univ
data BinTree a
= BinTip
| BinNode (BinTree a) a (BinTree a)
deriving (BinTree a -> BinTree a -> Bool
BinTree a -> BinTree a -> Ordering
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (BinTree a)
forall a. Ord a => BinTree a -> BinTree a -> Bool
forall a. Ord a => BinTree a -> BinTree a -> Ordering
forall a. Ord a => BinTree a -> BinTree a -> BinTree a
min :: BinTree a -> BinTree a -> BinTree a
$cmin :: forall a. Ord a => BinTree a -> BinTree a -> BinTree a
max :: BinTree a -> BinTree a -> BinTree a
$cmax :: forall a. Ord a => BinTree a -> BinTree a -> BinTree a
>= :: BinTree a -> BinTree a -> Bool
$c>= :: forall a. Ord a => BinTree a -> BinTree a -> Bool
> :: BinTree a -> BinTree a -> Bool
$c> :: forall a. Ord a => BinTree a -> BinTree a -> Bool
<= :: BinTree a -> BinTree a -> Bool
$c<= :: forall a. Ord a => BinTree a -> BinTree a -> Bool
< :: BinTree a -> BinTree a -> Bool
$c< :: forall a. Ord a => BinTree a -> BinTree a -> Bool
compare :: BinTree a -> BinTree a -> Ordering
$ccompare :: forall a. Ord a => BinTree a -> BinTree a -> Ordering
Ord, BinTree a -> BinTree a -> Bool
forall a. Eq a => BinTree a -> BinTree a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BinTree a -> BinTree a -> Bool
$c/= :: forall a. Eq a => BinTree a -> BinTree a -> Bool
== :: BinTree a -> BinTree a -> Bool
$c== :: forall a. Eq a => BinTree a -> BinTree a -> Bool
Eq, Int -> BinTree a -> ShowS
forall a. Show a => Int -> BinTree a -> ShowS
forall a. Show a => [BinTree a] -> ShowS
forall a. Show a => BinTree a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BinTree a] -> ShowS
$cshowList :: forall a. Show a => [BinTree a] -> ShowS
show :: BinTree a -> String
$cshow :: forall a. Show a => BinTree a -> String
showsPrec :: Int -> BinTree a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> BinTree a -> ShowS
Show, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (BinTree a) x -> BinTree a
forall a x. BinTree a -> Rep (BinTree a) x
$cto :: forall a x. Rep (BinTree a) x -> BinTree a
$cfrom :: forall a x. BinTree a -> Rep (BinTree a) x
Generic)
data BinTreeSpec fn a = BinTreeSpec (Maybe Integer) (Specification fn (BinTree a, a, BinTree a))
deriving (Int -> BinTreeSpec fn a -> ShowS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
Int -> BinTreeSpec fn a -> ShowS
forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
[BinTreeSpec fn a] -> ShowS
forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
BinTreeSpec fn a -> String
showList :: [BinTreeSpec fn a] -> ShowS
$cshowList :: forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
[BinTreeSpec fn a] -> ShowS
show :: BinTreeSpec fn a -> String
$cshow :: forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
BinTreeSpec fn a -> String
showsPrec :: Int -> BinTreeSpec fn a -> ShowS
$cshowsPrec :: forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
Int -> BinTreeSpec fn a -> ShowS
Show)
instance Forallable (BinTree a) (BinTree a, a, BinTree a) where
fromForAllSpec :: forall (fn :: [*] -> * -> *).
(HasSpec fn (BinTree a), HasSpec fn (BinTree a, a, BinTree a),
BaseUniverse fn) =>
Specification fn (BinTree a, a, BinTree a)
-> Specification fn (BinTree a)
fromForAllSpec = forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
TypeSpec fn a -> Specification fn a
typeSpec forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (fn :: [*] -> * -> *) a.
Maybe Integer
-> Specification fn (BinTree a, a, BinTree a) -> BinTreeSpec fn a
BinTreeSpec forall a. Maybe a
Nothing
forAllToList :: BinTree a -> [(BinTree a, a, BinTree a)]
forAllToList BinTree a
BinTip = []
forAllToList (BinNode BinTree a
left a
a BinTree a
right) = (BinTree a
left, a
a, BinTree a
right) forall a. a -> [a] -> [a]
: forall t e. Forallable t e => t -> [e]
forAllToList BinTree a
left forall a. [a] -> [a] -> [a]
++ forall t e. Forallable t e => t -> [e]
forAllToList BinTree a
right
instance HasSpec fn a => HasSpec fn (BinTree a) where
type TypeSpec fn (BinTree a) = BinTreeSpec fn a
emptySpec :: TypeSpec fn (BinTree a)
emptySpec = forall (fn :: [*] -> * -> *) a.
Maybe Integer
-> Specification fn (BinTree a, a, BinTree a) -> BinTreeSpec fn a
BinTreeSpec forall a. Maybe a
Nothing forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec
combineSpec :: TypeSpec fn (BinTree a)
-> TypeSpec fn (BinTree a) -> Specification fn (BinTree a)
combineSpec (BinTreeSpec Maybe Integer
sz Specification fn (BinTree a, a, BinTree a)
s) (BinTreeSpec Maybe Integer
sz' Specification fn (BinTree a, a, BinTree a)
s') =
forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
TypeSpec fn a -> Specification fn a
typeSpec forall a b. (a -> b) -> a -> b
$ forall (fn :: [*] -> * -> *) a.
Maybe Integer
-> Specification fn (BinTree a, a, BinTree a) -> BinTreeSpec fn a
BinTreeSpec (forall a. (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a
unionWithMaybe forall a. Ord a => a -> a -> a
min Maybe Integer
sz Maybe Integer
sz') (Specification fn (BinTree a, a, BinTree a)
s forall a. Semigroup a => a -> a -> a
<> Specification fn (BinTree a, a, BinTree a)
s')
conformsTo :: HasCallStack => BinTree a -> TypeSpec fn (BinTree a) -> Bool
conformsTo BinTree a
BinTip TypeSpec fn (BinTree a)
_ = Bool
True
conformsTo (BinNode BinTree a
left a
a BinTree a
right) s :: TypeSpec fn (BinTree a)
s@(BinTreeSpec Maybe Integer
_ Specification fn (BinTree a, a, BinTree a)
es) =
forall (t :: * -> *). Foldable t => t Bool -> Bool
and
[ (BinTree a
left, a
a, BinTree a
right) forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
a -> Specification fn a -> Bool
`conformsToSpec` Specification fn (BinTree a, a, BinTree a)
es
, BinTree a
left forall (fn :: [*] -> * -> *) a.
(HasSpec fn a, HasCallStack) =>
a -> TypeSpec fn a -> Bool
`conformsTo` TypeSpec fn (BinTree a)
s
, BinTree a
right forall (fn :: [*] -> * -> *) a.
(HasSpec fn a, HasCallStack) =>
a -> TypeSpec fn a -> Bool
`conformsTo` TypeSpec fn (BinTree a)
s
]
genFromTypeSpec :: forall (m :: * -> *).
(HasCallStack, MonadGenError m) =>
TypeSpec fn (BinTree a) -> GenT m (BinTree a)
genFromTypeSpec (BinTreeSpec Maybe Integer
msz Specification fn (BinTree a, a, BinTree a)
s)
| Just Integer
sz <- Maybe Integer
msz, Integer
sz forall a. Ord a => a -> a -> Bool
<= Integer
0 = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. BinTree a
BinTip
| Bool
otherwise = do
let sz :: Integer
sz = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Integer
20 forall a. a -> a
id Maybe Integer
msz
sz' :: Integer
sz' = Integer
sz forall a. Integral a => a -> a -> a
`div` Integer
2
forall (m :: * -> *) a. MonadGenError m => [GenT GE a] -> GenT m a
oneofT
[ do
(BinTree a
left, a
a, BinTree a
right) <- forall (fn :: [*] -> * -> *) a (m :: * -> *).
(HasCallStack, HasSpec fn a, MonadGenError m) =>
Specification fn a -> GenT m a
genFromSpecT @fn @(BinTree a, a, BinTree a) forall a b. (a -> b) -> a -> b
$
forall a (fn :: [*] -> * -> *) p.
(IsPred p fn, HasSpec fn a) =>
(Term fn a -> p) -> Specification fn a
constrained forall a b. (a -> b) -> a -> b
$ \Term fn (BinTree a, a, BinTree a)
ctx ->
[ forall (fn :: [*] -> * -> *) p a.
(HasSpec fn a, IsProductType fn a, IsPred p fn) =>
Term fn a
-> FunTy (MapList (Term fn) (ProductAsList a)) p -> Pred fn
match Term fn (BinTree a, a, BinTree a)
ctx forall a b. (a -> b) -> a -> b
$ \Term fn (BinTree a)
left Term fn a
_ Term fn (BinTree a)
right ->
[ forall t a (fn :: [*] -> * -> *) p.
(Forallable t a, HasSpec fn t, HasSpec fn a, IsPred p fn) =>
Term fn t -> (Term fn a -> p) -> Pred fn
forAll Term fn (BinTree a)
left (forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
Term fn a -> Specification fn a -> Pred fn
`satisfies` Specification fn (BinTree a, a, BinTree a)
s)
, forall (fn :: [*] -> * -> *) t.
HasGenHint fn t =>
Hint t -> Term fn t -> Pred fn
genHint Integer
sz' Term fn (BinTree a)
left
, forall t a (fn :: [*] -> * -> *) p.
(Forallable t a, HasSpec fn t, HasSpec fn a, IsPred p fn) =>
Term fn t -> (Term fn a -> p) -> Pred fn
forAll Term fn (BinTree a)
right (forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
Term fn a -> Specification fn a -> Pred fn
`satisfies` Specification fn (BinTree a, a, BinTree a)
s)
, forall (fn :: [*] -> * -> *) t.
HasGenHint fn t =>
Hint t -> Term fn t -> Pred fn
genHint Integer
sz' Term fn (BinTree a)
right
]
, Term fn (BinTree a, a, BinTree a)
ctx forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
Term fn a -> Specification fn a -> Pred fn
`satisfies` Specification fn (BinTree a, a, BinTree a)
s
]
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a. BinTree a -> a -> BinTree a -> BinTree a
BinNode BinTree a
left a
a BinTree a
right
, forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. BinTree a
BinTip
]
shrinkWithTypeSpec :: TypeSpec fn (BinTree a) -> BinTree a -> [BinTree a]
shrinkWithTypeSpec TypeSpec fn (BinTree a)
_ BinTree a
BinTip = []
shrinkWithTypeSpec TypeSpec fn (BinTree a)
s (BinNode BinTree a
left a
a BinTree a
right) =
forall a. BinTree a
BinTip
forall a. a -> [a] -> [a]
: BinTree a
left
forall a. a -> [a] -> [a]
: BinTree a
right
forall a. a -> [a] -> [a]
: (forall a. BinTree a -> a -> BinTree a -> BinTree a
BinNode BinTree a
left a
a forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
TypeSpec fn a -> a -> [a]
shrinkWithTypeSpec TypeSpec fn (BinTree a)
s BinTree a
right)
forall a. [a] -> [a] -> [a]
++ ((\BinTree a
l -> forall a. BinTree a -> a -> BinTree a -> BinTree a
BinNode BinTree a
l a
a BinTree a
right) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
TypeSpec fn a -> a -> [a]
shrinkWithTypeSpec TypeSpec fn (BinTree a)
s BinTree a
left)
cardinalTypeSpec :: TypeSpec fn (BinTree a) -> Specification fn Integer
cardinalTypeSpec TypeSpec fn (BinTree a)
_ = forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec
toPreds :: Term fn (BinTree a) -> TypeSpec fn (BinTree a) -> Pred fn
toPreds Term fn (BinTree a)
t (BinTreeSpec Maybe Integer
msz Specification fn (BinTree a, a, BinTree a)
s) =
(forall t a (fn :: [*] -> * -> *) p.
(Forallable t a, HasSpec fn t, HasSpec fn a, IsPred p fn) =>
Term fn t -> (Term fn a -> p) -> Pred fn
forAll Term fn (BinTree a)
t forall a b. (a -> b) -> a -> b
$ \Term fn (BinTree a, a, BinTree a)
n -> Term fn (BinTree a, a, BinTree a)
n forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
Term fn a -> Specification fn a -> Pred fn
`satisfies` Specification fn (BinTree a, a, BinTree a)
s)
forall a. Semigroup a => a -> a -> a
<> forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall (fn :: [*] -> * -> *). Pred fn
TruePred (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (fn :: [*] -> * -> *) t.
HasGenHint fn t =>
Hint t -> Term fn t -> Pred fn
genHint Term fn (BinTree a)
t) Maybe Integer
msz
instance HasSpec fn a => HasGenHint fn (BinTree a) where
type Hint (BinTree a) = Integer
giveHint :: Hint (BinTree a) -> Specification fn (BinTree a)
giveHint Hint (BinTree a)
h = forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
TypeSpec fn a -> Specification fn a
typeSpec forall a b. (a -> b) -> a -> b
$ forall (fn :: [*] -> * -> *) a.
Maybe Integer
-> Specification fn (BinTree a, a, BinTree a) -> BinTreeSpec fn a
BinTreeSpec (forall a. a -> Maybe a
Just Hint (BinTree a)
h) forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec
data TreeSpec fn a = TreeSpec
{ forall (fn :: [*] -> * -> *) a. TreeSpec fn a -> Maybe Integer
roseTreeAvgLength :: Maybe Integer
, forall (fn :: [*] -> * -> *) a. TreeSpec fn a -> Maybe Integer
roseTreeMaxSize :: Maybe Integer
, forall (fn :: [*] -> * -> *) a. TreeSpec fn a -> Specification fn a
roseTreeRootSpec :: Specification fn a
, forall (fn :: [*] -> * -> *) a.
TreeSpec fn a -> Specification fn (a, [Tree a])
roseTreeCtxSpec :: Specification fn (a, [Tree a])
}
deriving instance (HasSpec fn a, Member (TreeFn fn) fn) => Show (TreeSpec fn a)
instance Forallable (Tree a) (a, [Tree a]) where
fromForAllSpec :: forall (fn :: [*] -> * -> *).
(HasSpec fn (Tree a), HasSpec fn (a, [Tree a]), BaseUniverse fn) =>
Specification fn (a, [Tree a]) -> Specification fn (Tree a)
fromForAllSpec = forall (fn :: [*] -> * -> *) a.
HasSpec fn (Tree a) =>
TreeSpec fn a -> Specification fn (Tree a)
guardRoseSpec forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (fn :: [*] -> * -> *) a.
Maybe Integer
-> Maybe Integer
-> Specification fn a
-> Specification fn (a, [Tree a])
-> TreeSpec fn a
TreeSpec forall a. Maybe a
Nothing forall a. Maybe a
Nothing forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec
forAllToList :: Tree a -> [(a, [Tree a])]
forAllToList (Node a
a [Tree a]
children) = (a
a, [Tree a]
children) forall a. a -> [a] -> [a]
: forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap forall t e. Forallable t e => t -> [e]
forAllToList [Tree a]
children
guardRoseSpec :: HasSpec fn (Tree a) => TreeSpec fn a -> Specification fn (Tree a)
guardRoseSpec :: forall (fn :: [*] -> * -> *) a.
HasSpec fn (Tree a) =>
TreeSpec fn a -> Specification fn (Tree a)
guardRoseSpec spec :: TreeSpec fn a
spec@(TreeSpec Maybe Integer
_ Maybe Integer
_ Specification fn a
rs Specification fn (a, [Tree a])
s)
| forall (fn :: [*] -> * -> *) a. Specification fn a -> Bool
isErrorLike Specification fn a
rs = forall (fn :: [*] -> * -> *) a.
NonEmpty String -> Specification fn a
ErrorSpec (forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"guardRoseSpec: rootSpec is error")
| forall (fn :: [*] -> * -> *) a. Specification fn a -> Bool
isErrorLike Specification fn (a, [Tree a])
s = forall (fn :: [*] -> * -> *) a.
NonEmpty String -> Specification fn a
ErrorSpec (forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"guardRoseSpec: ctxSpec is error")
| Bool
otherwise = forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
TypeSpec fn a -> OrdSet a -> Specification fn a
TypeSpec TreeSpec fn a
spec []
instance (HasSpec fn a, Member (TreeFn fn) fn) => HasSpec fn (Tree a) where
type TypeSpec fn (Tree a) = TreeSpec fn a
emptySpec :: TypeSpec fn (Tree a)
emptySpec = forall (fn :: [*] -> * -> *) a.
Maybe Integer
-> Maybe Integer
-> Specification fn a
-> Specification fn (a, [Tree a])
-> TreeSpec fn a
TreeSpec forall a. Maybe a
Nothing forall a. Maybe a
Nothing forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec
combineSpec :: TypeSpec fn (Tree a)
-> TypeSpec fn (Tree a) -> Specification fn (Tree a)
combineSpec (TreeSpec Maybe Integer
mal Maybe Integer
sz Specification fn a
rs Specification fn (a, [Tree a])
s) (TreeSpec Maybe Integer
mal' Maybe Integer
sz' Specification fn a
rs' Specification fn (a, [Tree a])
s')
| forall (fn :: [*] -> * -> *) a. Specification fn a -> Bool
isErrorLike Specification fn (a, [Tree a])
alteredspec = forall (fn :: [*] -> * -> *) a.
NonEmpty String -> Specification fn a
ErrorSpec (forall (fn :: [*] -> * -> *) a.
Specification fn a -> NonEmpty String
errorLikeMessage Specification fn (a, [Tree a])
alteredspec)
| Bool
otherwise =
forall (fn :: [*] -> * -> *) a.
HasSpec fn (Tree a) =>
TreeSpec fn a -> Specification fn (Tree a)
guardRoseSpec forall a b. (a -> b) -> a -> b
$
forall (fn :: [*] -> * -> *) a.
Maybe Integer
-> Maybe Integer
-> Specification fn a
-> Specification fn (a, [Tree a])
-> TreeSpec fn a
TreeSpec
(forall a. (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a
unionWithMaybe forall a. Ord a => a -> a -> a
max Maybe Integer
mal Maybe Integer
mal')
(forall a. (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a
unionWithMaybe forall a. Ord a => a -> a -> a
min Maybe Integer
sz Maybe Integer
sz')
Specification fn a
rs''
Specification fn (a, [Tree a])
s''
where
alteredspec :: Specification fn (a, [Tree a])
alteredspec = (forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
TypeSpec fn a -> Specification fn a
typeSpec (forall (fn :: [*] -> * -> *) a b.
Specification fn a -> Specification fn b -> PairSpec fn a b
Cartesian Specification fn a
rs'' forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec) forall a. Semigroup a => a -> a -> a
<> Specification fn (a, [Tree a])
s'')
rs'' :: Specification fn a
rs'' = Specification fn a
rs forall a. Semigroup a => a -> a -> a
<> Specification fn a
rs'
s'' :: Specification fn (a, [Tree a])
s'' = Specification fn (a, [Tree a])
s forall a. Semigroup a => a -> a -> a
<> Specification fn (a, [Tree a])
s'
conformsTo :: HasCallStack => Tree a -> TypeSpec fn (Tree a) -> Bool
conformsTo (Node a
a [Tree a]
children) (TreeSpec Maybe Integer
_ Maybe Integer
_ Specification fn a
rs Specification fn (a, [Tree a])
s) =
forall (t :: * -> *). Foldable t => t Bool -> Bool
and
[ (a
a, [Tree a]
children) forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
a -> Specification fn a -> Bool
`conformsToSpec` Specification fn (a, [Tree a])
s
, forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (\(Node a
a' [Tree a]
children') -> (a
a', [Tree a]
children') forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
a -> Specification fn a -> Bool
`conformsToSpec` Specification fn (a, [Tree a])
s) [Tree a]
children
, a
a forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
a -> Specification fn a -> Bool
`conformsToSpec` Specification fn a
rs
]
genFromTypeSpec :: forall (m :: * -> *).
(HasCallStack, MonadGenError m) =>
TypeSpec fn (Tree a) -> GenT m (Tree a)
genFromTypeSpec (TreeSpec Maybe Integer
mal Maybe Integer
msz Specification fn a
rs Specification fn (a, [Tree a])
s) = do
let sz :: Integer
sz = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Integer
20 forall a. a -> a
id Maybe Integer
msz
sz' :: Integer
sz' = forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Integer
sz forall a. Integral a => a -> a -> a
`div` Integer
4) (Integer
sz forall a. Integral a => a -> a -> a
`div`) Maybe Integer
mal
childrenSpec :: Specification fn [Tree a]
childrenSpec =
forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
TypeSpec fn a -> Specification fn a
typeSpec forall a b. (a -> b) -> a -> b
$
forall (fn :: [*] -> * -> *) a.
Maybe Integer
-> [a]
-> Specification fn Integer
-> Specification fn a
-> FoldSpec fn a
-> ListSpec fn a
ListSpec
(forall a. a -> Maybe a
Just Integer
sz')
[]
forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec
(forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
TypeSpec fn a -> Specification fn a
typeSpec forall a b. (a -> b) -> a -> b
$ forall (fn :: [*] -> * -> *) a.
Maybe Integer
-> Maybe Integer
-> Specification fn a
-> Specification fn (a, [Tree a])
-> TreeSpec fn a
TreeSpec Maybe Integer
mal (forall a. a -> Maybe a
Just Integer
sz') forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec Specification fn (a, [Tree a])
s)
forall (fn :: [*] -> * -> *) a. FoldSpec fn a
NoFold
innerSpec :: Specification fn (a, [Tree a])
innerSpec = Specification fn (a, [Tree a])
s forall a. Semigroup a => a -> a -> a
<> forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
TypeSpec fn a -> Specification fn a
typeSpec (forall (fn :: [*] -> * -> *) a b.
Specification fn a -> Specification fn b -> PairSpec fn a b
Cartesian Specification fn a
rs Specification fn [Tree a]
childrenSpec)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall a. a -> [Tree a] -> Tree a
Node) forall a b. (a -> b) -> a -> b
$
forall (fn :: [*] -> * -> *) a (m :: * -> *).
(HasCallStack, HasSpec fn a, MonadGenError m) =>
Specification fn a -> GenT m a
genFromSpecT @fn @(a, [Tree a]) Specification fn (a, [Tree a])
innerSpec
shrinkWithTypeSpec :: TypeSpec fn (Tree a) -> Tree a -> [Tree a]
shrinkWithTypeSpec (TreeSpec Maybe Integer
_ Maybe Integer
_ Specification fn a
rs Specification fn (a, [Tree a])
ctxSpec) (Node a
a [Tree a]
ts) =
[forall a. a -> [Tree a] -> Tree a
Node a
a [] | Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Tree a]
ts]
forall a. [a] -> [a] -> [a]
++ [Tree a]
ts
forall a. [a] -> [a] -> [a]
++ [forall a. a -> [Tree a] -> Tree a
Node a
a' [Tree a]
ts | a
a' <- forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
Specification fn a -> a -> [a]
shrinkWithSpec Specification fn a
rs a
a]
forall a. [a] -> [a] -> [a]
++ [forall a. a -> [Tree a] -> Tree a
Node a
a [Tree a
t] | Tree a
t <- [Tree a]
ts]
forall a. [a] -> [a] -> [a]
++ [ forall a. a -> [Tree a] -> Tree a
Node a
a [Tree a]
ts'
| [Tree a]
ts' <- forall a. (a -> [a]) -> [a] -> [[a]]
shrinkList (forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
TypeSpec fn a -> a -> [a]
shrinkWithTypeSpec (forall (fn :: [*] -> * -> *) a.
Maybe Integer
-> Maybe Integer
-> Specification fn a
-> Specification fn (a, [Tree a])
-> TreeSpec fn a
TreeSpec forall a. Maybe a
Nothing forall a. Maybe a
Nothing forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec Specification fn (a, [Tree a])
ctxSpec)) [Tree a]
ts
]
cardinalTypeSpec :: TypeSpec fn (Tree a) -> Specification fn Integer
cardinalTypeSpec TypeSpec fn (Tree a)
_ = forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec
toPreds :: Term fn (Tree a) -> TypeSpec fn (Tree a) -> Pred fn
toPreds Term fn (Tree a)
t (TreeSpec Maybe Integer
mal Maybe Integer
msz Specification fn a
rs Specification fn (a, [Tree a])
s) =
(forall t a (fn :: [*] -> * -> *) p.
(Forallable t a, HasSpec fn t, HasSpec fn a, IsPred p fn) =>
Term fn t -> (Term fn a -> p) -> Pred fn
forAll Term fn (Tree a)
t forall a b. (a -> b) -> a -> b
$ \Term fn (a, [Tree a])
n -> Term fn (a, [Tree a])
n forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
Term fn a -> Specification fn a -> Pred fn
`satisfies` Specification fn (a, [Tree a])
s)
forall a. Semigroup a => a -> a -> a
<> forall (fn :: [*] -> * -> *) a.
(Member (TreeFn fn) fn, HasSpec fn a) =>
Term fn (Tree a) -> Term fn a
rootLabel_ Term fn (Tree a)
t forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
Term fn a -> Specification fn a -> Pred fn
`satisfies` Specification fn a
rs
forall a. Semigroup a => a -> a -> a
<> forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall (fn :: [*] -> * -> *). Pred fn
TruePred (\Integer
sz -> forall (fn :: [*] -> * -> *) t.
HasGenHint fn t =>
Hint t -> Term fn t -> Pred fn
genHint (Maybe Integer
mal, Integer
sz) Term fn (Tree a)
t) Maybe Integer
msz
instance (Member (TreeFn fn) fn, HasSpec fn a) => HasGenHint fn (Tree a) where
type Hint (Tree a) = (Maybe Integer, Integer)
giveHint :: Hint (Tree a) -> Specification fn (Tree a)
giveHint (Maybe Integer
avgLen, Integer
sz) = forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
TypeSpec fn a -> Specification fn a
typeSpec forall a b. (a -> b) -> a -> b
$ forall (fn :: [*] -> * -> *) a.
Maybe Integer
-> Maybe Integer
-> Specification fn a
-> Specification fn (a, [Tree a])
-> TreeSpec fn a
TreeSpec Maybe Integer
avgLen (forall a. a -> Maybe a
Just Integer
sz) forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec
data TreeFn (fn :: [Type] -> Type -> Type) args res where
RootLabel :: TreeFn fn '[Tree a] a
deriving instance Eq (TreeFn fn args res)
deriving instance Show (TreeFn fn args res)
instance FunctionLike (TreeFn fn) where
sem :: forall (as :: [*]) b. TreeFn fn as b -> FunTy as b
sem TreeFn fn as b
RootLabel = \(Node b
a [Tree b]
_) -> b
a
instance (Member (TreeFn fn) fn, BaseUniverse fn) => Functions (TreeFn fn) fn where
propagateSpecFun :: forall (as :: [*]) a b.
(TypeList as, Typeable as, HasSpec fn a, HasSpec fn b,
All (HasSpec fn) as) =>
TreeFn fn as b
-> ListCtx Value as (HOLE a)
-> Specification fn b
-> Specification fn a
propagateSpecFun TreeFn fn as b
_ ListCtx Value as (HOLE a)
_ Specification fn b
TrueSpec = forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec
propagateSpecFun TreeFn fn as b
_ ListCtx Value as (HOLE a)
_ (ErrorSpec NonEmpty String
err) = forall (fn :: [*] -> * -> *) a.
NonEmpty String -> Specification fn a
ErrorSpec NonEmpty String
err
propagateSpecFun TreeFn fn as b
fn ListCtx Value as (HOLE a)
ctx Specification fn b
spec = case TreeFn fn as b
fn of
TreeFn fn as b
_
| SuspendedSpec Var b
v Pred fn
ps <- Specification fn b
spec
, ListCtx List Value as
pre HOLE a a
HOLE List Value as'
suf <- ListCtx Value as (HOLE a)
ctx ->
forall a (fn :: [*] -> * -> *) p.
(IsPred p fn, HasSpec fn a) =>
(Term fn a -> p) -> Specification fn a
constrained forall a b. (a -> b) -> a -> b
$ \Term fn a
v' ->
let args :: List (Term fn) (Append as (a : as'))
args = forall {a} (f :: a -> *) (as :: [a]) (bs :: [a]).
List f as -> List f bs -> List f (Append as bs)
appendList (forall {k} (f :: k -> *) (g :: k -> *) (as :: [k]).
(forall (a :: k). f a -> g a) -> List f as -> List g as
mapList (\(Value a
a) -> forall a (fn :: [*] -> * -> *). Show a => a -> Term fn a
Lit a
a) List Value as
pre) (Term fn a
v' forall {k} (f :: k -> *) (a :: k) (as1 :: [k]).
f a -> List f as1 -> List f (a : as1)
:> forall {k} (f :: k -> *) (g :: k -> *) (as :: [k]).
(forall (a :: k). f a -> g a) -> List f as -> List g as
mapList (\(Value a
a) -> forall a (fn :: [*] -> * -> *). Show a => a -> Term fn a
Lit a
a) List Value as'
suf)
in forall (fn :: [*] -> * -> *) a. Term fn a -> Binder fn a -> Pred fn
Let (forall (as :: [*]) (fn :: [*] -> * -> *) a.
(Typeable as, TypeList as, All (HasSpec fn) as, HasSpec fn a,
BaseUniverse fn) =>
fn as a -> List (Term fn) as -> Term fn a
App (forall (fn :: [*] -> * -> *) (fnU :: [*] -> * -> *) (as :: [*]) b.
Member fn fnU =>
fn as b -> fnU as b
injectFn TreeFn fn as b
fn) List (Term fn) (Append as (a : as'))
args) (Var b
v forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
Var a -> Pred fn -> Binder fn a
:-> Pred fn
ps)
TreeFn fn as b
RootLabel ->
case TreeFn fn as b
fn of
(TreeFn fn '[Tree b] b
_ :: TreeFn fn '[Tree a] a)
| NilCtx HOLE a (Tree b)
HOLE <- ListCtx Value as (HOLE a)
ctx -> forall (fn :: [*] -> * -> *) a.
HasSpec fn a =>
TypeSpec fn a -> Specification fn a
typeSpec forall a b. (a -> b) -> a -> b
$ forall (fn :: [*] -> * -> *) a.
Maybe Integer
-> Maybe Integer
-> Specification fn a
-> Specification fn (a, [Tree a])
-> TreeSpec fn a
TreeSpec forall a. Maybe a
Nothing forall a. Maybe a
Nothing Specification fn b
spec forall (fn :: [*] -> * -> *) a. Specification fn a
TrueSpec
mapTypeSpec :: forall a b.
(HasSpec fn a, HasSpec fn b) =>
TreeFn fn '[a] b -> TypeSpec fn a -> Specification fn b
mapTypeSpec TreeFn fn '[a] b
f TypeSpec fn a
ts = case TreeFn fn '[a] b
f of
TreeFn fn '[a] b
RootLabel ->
case TreeFn fn '[a] b
f of
(TreeFn fn '[Tree b] b
_ :: TreeFn fn '[Tree a] a)
| TreeSpec Maybe Integer
_ Maybe Integer
_ Specification fn b
rs Specification fn (b, [Tree b])
_ <- TypeSpec fn a
ts -> Specification fn b
rs
rootLabel_ ::
forall fn a.
(Member (TreeFn fn) fn, HasSpec fn a) =>
Term fn (Tree a) ->
Term fn a
rootLabel_ :: forall (fn :: [*] -> * -> *) a.
(Member (TreeFn fn) fn, HasSpec fn a) =>
Term fn (Tree a) -> Term fn a
rootLabel_ = forall (fn :: [*] -> * -> *) b (as :: [*]).
(HasSpec fn b, Typeable as, TypeList as, All (HasSpec fn) as) =>
fn as b -> FunTy (MapList (Term fn) as) (Term fn b)
app (forall (fn :: [*] -> * -> *) (fnU :: [*] -> * -> *) (as :: [*]) b.
Member fn fnU =>
fn as b -> fnU as b
injectFn forall a b. (a -> b) -> a -> b
$ forall (fn :: [*] -> * -> *) a. TreeFn fn '[Tree a] a
RootLabel @fn)