Skip to content

Commit aa93057

Browse files
some more docs
1 parent 0f9dddd commit aa93057

File tree

14 files changed

+193
-176
lines changed

14 files changed

+193
-176
lines changed

docs/constrained-generators/DesignPrinciples.md

Lines changed: 110 additions & 110 deletions
Large diffs are not rendered by default.

libs/constrained-generators/src/Constrained/AbstractSyntax.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ data PredD deps where
250250
TermD deps Bool ->
251251
PredD deps ->
252252
PredD deps
253-
GenHint ::
253+
GenHintD ::
254254
( HasGenHintD deps a
255255
, Show a
256256
, Show (HintD deps a)
@@ -321,7 +321,7 @@ instance Pretty (PredD deps) where
321321
Case t bs -> "case" <+> pretty t <+> "of" /> vsep' (ppList pretty bs)
322322
When b p -> "whenTrue" <+> pretty (WithPrec 11 b) <+> "$" /> pretty p
323323
Subst x t p -> "[" <> pretty t <> "/" <> viaShow x <> "]" <> pretty p
324-
GenHint h t -> "genHint" <+> fromString (showsPrec 11 h "") <+> "$" <+> pretty t
324+
GenHintD h t -> "genHint" <+> fromString (showsPrec 11 h "") <+> "$" <+> pretty t
325325
TruePred -> "True"
326326
FalsePred {} -> "False"
327327
Monitor {} -> "monitor"

libs/constrained-generators/src/Constrained/Base.hs

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -33,53 +33,62 @@ module Constrained.Base (
3333
pattern (:>:),
3434
pattern Unary,
3535

36-
-- * Useful function symbols
36+
toCtx,
37+
flipCtx,
38+
fromListCtx,
39+
40+
-- * Useful function symbols and patterns for building custom rewrite rules
3741
fromGeneric_,
3842
toGeneric_,
3943

40-
-- * TODO: documentme
41-
HasSpec (..),
42-
propagateSpec,
4344
pattern ToGeneric,
4445
pattern FromGeneric,
46+
47+
-- * Syntax for building specifications
4548
constrained,
46-
appFun,
47-
errorLikeMessage,
48-
isErrorLike,
4949
notMemberSpec,
5050
notEqualSpec,
51+
typeSpec,
5152
addToErrorSpec,
52-
memberSpecList,
53-
toCtx,
54-
flipCtx,
55-
BinaryShow (..),
56-
name,
53+
memberSpec,
5754
fromSimpleRepSpec,
5855
toSimpleRepSpec,
59-
toPred,
60-
forAllToList,
6156
explainSpec,
62-
bind,
57+
58+
-- * Instantiated types and helper patterns
6359
Term,
6460
Specification,
6561
Pred,
66-
IsPred,
67-
HintF (..),
6862
Binder,
63+
64+
pattern TypeSpec,
65+
pattern GenHint,
66+
67+
-- * Constraints and classes
68+
HasSpec (..),
6969
HasGenHint (..),
7070
Forallable,
71-
pattern TypeSpec,
72-
typeSpec,
71+
AppRequires,
72+
GenericallyInstantiated,
73+
GenericRequires,
74+
75+
-- * TODO: documentme
76+
propagateSpec,
77+
appFun,
78+
errorLikeMessage,
79+
isErrorLike,
80+
BinaryShow (..),
81+
name,
82+
toPred,
83+
forAllToList,
84+
bind,
85+
IsPred,
7386
equalSpec,
7487
appTerm,
75-
GenericRequires,
7688
HOLE (..),
77-
AppRequires,
7889
fromForAllSpec,
7990
Fun (..),
80-
GenericallyInstantiated,
8191
BaseW (..),
82-
fromListCtx,
8392
) where
8493

8594
import Constrained.AbstractSyntax
@@ -129,22 +138,38 @@ instance Dependencies Deps where
129138

130139
type Binder = BinderD Deps
131140

141+
-- | All the constraints needed for application in the first order term languge
132142
type AppRequires t as b = AppRequiresD Deps t as b
133143

144+
-- | Predicates over `Term`s
134145
type Pred = PredD Deps
135146

147+
-- | First-order language of variables, literals, and application
136148
type Term = TermD Deps
137149

150+
-- | Specifications for generators instantiated with the `HasSpec` et al actual
151+
-- classes
138152
type Specification = SpecificationD Deps
139153

154+
-- | Pattern match out a `TypeSpec` and the can't-"set" - avoids some tedious
155+
-- pitfalls related to the `Deps` and `Dependencies` trick
140156
pattern TypeSpec :: () => HasSpec a => TypeSpec a -> [a] -> Specification a
141157
pattern TypeSpec ts cant = TypeSpecD (TypeSpecF ts) cant
142158

143159
{-# COMPLETE ExplainSpec, MemberSpec, ErrorSpec, SuspendedSpec, TypeSpec, TrueSpec #-}
144160

161+
-- | Build a specifiation from just a `TypeSpec`, useful internal function when
162+
-- writing `Logic` instances
145163
typeSpec :: HasSpec a => TypeSpec a -> Specification a
146164
typeSpec ts = TypeSpec ts mempty
147165

166+
-- | Pattern match out a `Hint` and the `Term` it applies to - avoids some
167+
-- tedious pitfalls related to the `Deps` and `Dependencies` trick
168+
pattern GenHint :: () => HasGenHint a => Hint a -> Term a -> Pred
169+
pattern GenHint h t = GenHintD (HintF h) t
170+
171+
{-# COMPLETE ElemPred, Monitor, And, Exists, Subst, Let, Assert, Reifies, DependsOn, ForAll, Case, When, GenHint, TruePred, FalsePred, Explain #-}
172+
148173
-- ====================================================================
149174

150175
-- | A First-order typed logic has 4 components
@@ -735,7 +760,7 @@ bind bodyf = newv :-> bodyPred
735760
bound (Case _ cs) = getMax $ foldMapList (Max . boundBinder . thing) cs
736761
bound (When _ p) = bound p
737762
bound Reifies {} = -1
738-
bound GenHint {} = -1
763+
bound GenHintD {} = -1
739764
bound Assert {} = -1
740765
bound DependsOn {} = -1
741766
bound TruePred = -1
@@ -793,27 +818,33 @@ instance IsPred (Term Bool) where
793818
-- ============================================================
794819
-- Simple Widely used operations on Specification
795820

796-
-- | return a MemberSpec or ans ErrorSpec depending on if 'xs' the null list or not
797-
memberSpecList :: [a] -> NE.NonEmpty String -> Specification a
798-
memberSpecList xs messages =
821+
-- | return a MemberSpec or ans ErrorSpec depending on if 'xs' is null or not
822+
memberSpec :: Foldable f => f a -> NE.NonEmpty String -> Specification a
823+
memberSpec (toList -> xs) messages =
799824
case NE.nonEmpty xs of
800825
Nothing -> ErrorSpec messages
801826
Just ys -> MemberSpec ys
802827

828+
-- | Attach an explanation to a specification in order to track issues with satisfiability
803829
explainSpec :: [String] -> Specification a -> Specification a
804830
explainSpec [] x = x
805831
explainSpec es (ExplainSpec es' spec) = ExplainSpec (es ++ es') spec
806832
explainSpec es spec = ExplainSpec es spec
807833

834+
-- | A "discrete" specification satisfied by exactly one element
808835
equalSpec :: a -> Specification a
809836
equalSpec = MemberSpec . pure
810837

838+
-- | Anything but this
811839
notEqualSpec :: forall a. HasSpec a => a -> Specification a
812840
notEqualSpec = TypeSpec (emptySpec @a) . pure
813841

842+
-- | Anything but these
814843
notMemberSpec :: forall a f. (HasSpec a, Foldable f) => f a -> Specification a
815844
notMemberSpec = typeSpecOpt (emptySpec @a) . toList
816845

846+
-- | Build a `Specification` using predicates, e.g.
847+
-- > constrained $ \ x -> assert $ x `elem_` lit [1..10 :: Int]
817848
constrained ::
818849
forall a p.
819850
(IsPred p, HasSpec a) =>
@@ -823,6 +854,7 @@ constrained body =
823854
let x :-> p = bind body
824855
in SuspendedSpec x p
825856

857+
-- | Sound but not complete check for empty `Specification`s
826858
isErrorLike :: forall a. Specification a -> Bool
827859
isErrorLike (ExplainSpec _ s) = isErrorLike s
828860
isErrorLike ErrorSpec {} = True
@@ -832,6 +864,7 @@ isErrorLike (TypeSpec x _) =
832864
Just _ -> True
833865
isErrorLike _ = False
834866

867+
-- | Get the error message of an `isErrorLike` `Specification`
835868
errorLikeMessage :: forall a. Specification a -> NE.NonEmpty String
836869
errorLikeMessage (ErrorSpec es) = es
837870
errorLikeMessage (TypeSpec x _) =

libs/constrained-generators/src/Constrained/Conformance.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,12 +252,12 @@ instance HasSpec a => Semigroup (Specification a) where
252252
( NE.fromList
253253
["Intersecting: ", " MemberSpec " ++ show (NE.toList as), " MemberSpec " ++ show (NE.toList as')]
254254
)
255-
( memberSpecList
255+
( memberSpec
256256
(nub $ intersect (NE.toList as) (NE.toList as'))
257257
(pure "Empty intersection")
258258
)
259259
ms@(MemberSpec as) <> ts@TypeSpec {} =
260-
memberSpecList
260+
memberSpec
261261
(nub $ NE.filter (`conformsToSpec` ts) as)
262262
( NE.fromList
263263
[ "The two " ++ showType @a ++ " Specifications are inconsistent."

libs/constrained-generators/src/Constrained/Generation.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ computeSpecSimplified x pred3 = localGESpec $ case simplifyPred pred3 of
336336
ElemPred True t xs -> propagateSpec (MemberSpec xs) <$> toCtx x t
337337
ElemPred False (t :: Term b) xs -> propagateSpec (TypeSpec @b (emptySpec @b) (NE.toList xs)) <$> toCtx x t
338338
Monitor {} -> pure mempty
339-
GenHint (HintF h) t -> propagateSpec (giveHint h) <$> toCtx x t
339+
GenHint h t -> propagateSpec (giveHint h) <$> toCtx x t
340340
Subst x' t p' -> computeSpec x (substitutePred x' t p') -- NOTE: this is impossible as it should have gone away already
341341
TruePred -> pure mempty
342342
FalsePred es -> genErrorNE es

libs/constrained-generators/src/Constrained/NumOrd.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import Constrained.Base (
3636
explainSpec,
3737
flipCtx,
3838
fromSimpleRepSpec,
39-
memberSpecList,
39+
memberSpec,
4040
notMemberSpec,
4141
typeSpec,
4242
pattern TypeSpec,
@@ -359,7 +359,7 @@ nubOrd =
359359
-- | Builds a MemberSpec, but returns an Error spec if the list is empty
360360
nubOrdMemberSpec :: Ord a => String -> [a] -> Specification a
361361
nubOrdMemberSpec message xs =
362-
memberSpecList
362+
memberSpec
363363
(nubOrd xs)
364364
( NE.fromList
365365
[ "In call to nubOrdMemberSpec"
@@ -751,7 +751,7 @@ instance Logic IntW where
751751
propagateTypeSpec NegateW (Unary HOLE) ts cant = negateSpec ts <> notMemberSpec (map negate cant)
752752

753753
propagateMemberSpec AddW (HOLE :<: i) es =
754-
memberSpecList
754+
memberSpec
755755
(nub $ mapMaybe (safeSubtract i) (NE.toList es))
756756
( NE.fromList
757757
[ "propagateSpecFn on (" ++ show i ++ " +. HOLE)"

libs/constrained-generators/src/Constrained/Spec/List.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ instance Logic ElemW where
163163
constrained $ \v' -> Let (App ElemW (Lit x :> v' :> Nil)) (v :-> ps)
164164
propagate ElemW (HOLE :<: es) spec =
165165
caseBoolSpec spec $ \case
166-
True -> memberSpecList (nub es) (pure "propagate on (elem_ x []), The empty list, [], has no solution")
166+
True -> memberSpec (nub es) (pure "propagate on (elem_ x []), The empty list, [], has no solution")
167167
False -> notMemberSpec es
168168
propagate ElemW (e :>: HOLE) spec =
169169
caseBoolSpec spec $ \case

libs/constrained-generators/src/Constrained/Spec/Map.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ instance Logic MapW where
364364
if Nothing `conformsToSpec` spec
365365
then notMemberSpec [k | (k, v) <- Map.toList m, not $ Just v `conformsToSpec` spec]
366366
else
367-
memberSpecList
367+
memberSpec
368368
(Map.keys $ Map.filter ((`conformsToSpec` spec) . Just) m)
369369
( NE.fromList
370370
[ "propagate (lookup HOLE ms) on (MemberSpec ms)"

libs/constrained-generators/src/Constrained/Spec/Set.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ instance Logic SetW where
325325
typeSpec
326326
( SetSpec
327327
(Set.difference e s)
328-
( memberSpecList
328+
( memberSpec
329329
(Set.toList e)
330330
(pure "propagateSpec (union_ s HOLE) on (MemberSpec [e]) where e is the empty set")
331331
)
@@ -364,7 +364,7 @@ instance Logic SetW where
364364
]
365365
propagate MemberW ctx spec
366366
| (HOLE :? Value s :> Nil) <- ctx = caseBoolSpec spec $ \case
367-
True -> memberSpecList (Set.toList s) (pure "propagateSpecFun on (Member x s) where s is Set.empty")
367+
True -> memberSpec (Set.toList s) (pure "propagateSpecFun on (Member x s) where s is Set.empty")
368368
False -> notMemberSpec s
369369
| (Value e :! Unary HOLE) <- ctx = caseBoolSpec spec $ \case
370370
True -> typeSpec $ SetSpec (Set.singleton e) mempty mempty
@@ -389,7 +389,7 @@ instance Logic SetW where
389389
Nothing
390390
(Set.toList xs)
391391
TrueSpec
392-
( memberSpecList
392+
( memberSpec
393393
(Set.toList xs)
394394
(pure "propagateSpec (fromList_ HOLE) on (MemberSpec xs) where the set 'xs' is empty")
395395
)

libs/constrained-generators/src/Constrained/SumList.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ genNumList elemSIn foldSIn = do
195195

196196
buildMemberSpec _ 0 es _ =
197197
pure
198-
( memberSpecList
198+
( memberSpec
199199
(Set.toList es)
200200
(pure "In genNumList, in buildMemberSpec 'es' is the empty list, can't make a MemberSpec from that")
201201
)
@@ -409,7 +409,7 @@ narrowByFuelAndSize fuel size specpair =
409409
possible x = x == u || xMinP <= u - x
410410
xs' = filter possible xs
411411
, xs' /= xs =
412-
Just (memberSpecList (nubOrd xs') (pure ("None of " ++ show xs ++ " are possible")), foldS)
412+
Just (memberSpec (nubOrd xs') (pure ("None of " ++ show xs ++ " are possible")), foldS)
413413
-- The lower bound on the number of elements is too low
414414
| Just e <- knownLowerBound elemS
415415
, e > 0

0 commit comments

Comments
 (0)