Skip to content

Commit 084e89e

Browse files
Syntax highlighting
1 parent d936bea commit 084e89e

File tree

1 file changed

+47
-47
lines changed

1 file changed

+47
-47
lines changed

docs/Manual.md

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -532,8 +532,8 @@ match p $ \ x y -> x <. y
532532
In previous sections we provided some types for several of the library functions: `constrained`, `match`,
533533
534534
535-
```
536-
constrained:: HasSpec a => (Term a -> Pred) -> Specification a
535+
```haskell
536+
constrained :: HasSpec a => (Term a -> Pred) -> Specification a
537537
538538
match :: (HasSpec a, HasSpec b) =>
539539
Term (a,b) -> (Term a -> Term b -> Pred) -> Pred
@@ -542,14 +542,14 @@ match :: (HasSpec a, HasSpec b) =>
542542
It turns out, that these functions would be much more useful with more general types. This also applies to some other
543543
library functions (`reify`, `caseOn`, etc.) we have not yet introduced. The general type of `constrained` is:
544544

545-
```
546-
constrained:: (IsPred p, HasSpec a) => (Term a -> p) -> Specification a
545+
```haskell
546+
constrained :: (IsPred p, HasSpec a) => (Term a -> p) -> Specification a
547547
```
548548

549549
This general type allows the function passed to `constrained` to be any function, that given a Term, returns any type that acts like a `Pred`.
550550
The class IsPred is defined as follows, and has 4 instances.
551551

552-
```
552+
```haskell
553553
class Show p => IsPred p where
554554
toPred :: p -> Pred
555555

@@ -615,7 +615,7 @@ type FunTy (MapList Term (ProductAsList a)) p = t1 -> t2 -> ... -> tn -> p
615615
616616
`assert` lifts a `(Term Bool)` to a `Pred`. by using the `IsPred` class, we can often get around using it, but it becomes necessary when we want to use the `And` operator, and the operands of `And` are a mix of `Pred`, `(Term Bool), and other operations. Here is a very simple use. Further examples illustrate its use in more challenging contexts.
617617
618-
```
618+
```haskell
619619
ex5 :: Specification [Int]
620620
ex5 = constrained $ \ xs -> assert $ elem_ 7 xs
621621
```
@@ -628,7 +628,7 @@ Note that `elem_` is the function symbol corresponding to `Data.List.elem`.
628628
The library function `forAll` is used to impose a constraint on every element of a container type. There are
629629
three `Forallable` instances in the Base system.
630630

631-
```
631+
```haskell
632632
class Forallable t e | t -> e where
633633
instance Ord k => Forallable (Map k v) (k, v)
634634
instance Ord a => Forallable (Set a) a
@@ -637,7 +637,7 @@ instance Forallable [a] a
637637

638638
Here is an example of its use.
639639

640-
```
640+
```haskell
641641
ex6 :: Specification [Int]
642642
ex6 = constrained $ \ xs ->
643643
forAll xs $ \ x -> [ x <=. 10, x >. 1]
@@ -683,7 +683,7 @@ The first use: `(reifies b a f)`, says a term `b` can be obtained from a term `
683683
Here is an example of its use. Internally, it works by forcing the solution of `a` before solving for `b`, applying the `f` to
684684
the solution for `a`, and then constructing a `(Term b)` obtained from this value.
685685

686-
```
686+
```haskell
687687
ex7 :: Specification (Int,[Int])
688688
ex7 = constrained $ \ pair ->
689689
match pair $ \ n xs ->
@@ -707,7 +707,7 @@ True
707707
The second operation `reify` can be defined using `reifies` by placing an existential constraint on the range of the function.
708708
Here is an example of the use of `reify`
709709

710-
```
710+
```haskell
711711
ex8 :: Specification ([Int],[Int])
712712
ex8 = constrained $ \ pair ->
713713
match pair $ \ xs1 xs2 ->
@@ -737,7 +737,7 @@ True
737737
The third operation `assertReified` can be used to place a boolean constraint on the existential.
738738
Here is an example of its use.
739739

740-
```
740+
```haskell
741741
ex9 :: Specification Int
742742
ex9 = constrained $ \x ->
743743
[ assert $ x <=. 10
@@ -770,7 +770,7 @@ Sometimes we want to choose between several different specifications for the sam
770770
Let's look at the first. Multiple constuctors from the same type. This uses the `caseOn` library functions and its two
771771
helper functions `branch` (where each constructor is choosen equally) and `branchW` (where we can give weights, to determine the frequency each constructor is choosen). The type of `caseOn`
772772

773-
```
773+
```haskell
774774
caseOn
775775
:: Term a
776776
-> FunTy
@@ -785,15 +785,15 @@ unweighted using `(branch ...)`, where the `...` is a function with *m* paramete
785785
subcomponents of that constructor). First we introduce a sum of products type `Three` and use the GHC.Generics
786786
instance to derive the HasSpec instance.
787787

788-
```
788+
```haskell
789789
data Three = One Int | Two Bool | Three Int deriving (Ord, Eq, Show, Generic)
790790
instance HasSimpleRep Three
791791
instance HasSpec Three
792792
```
793793

794794
Here is an example using the mechanism with no weights (`branch`), where every branch is equilikely.
795795

796-
```
796+
```haskell
797797
ex10 :: Specification Three
798798
ex10 = constrained $ \ three ->
799799
caseOn three
@@ -807,7 +807,7 @@ expects the branches to be in the same order the constructors are introduced in
807807

808808
Here is another example using the weighted mechanism (`branchW`).
809809

810-
```
810+
```haskell
811811
ex11 :: Specification Three
812812
ex11 = constrained $ \ three ->
813813
caseOn three
@@ -824,13 +824,13 @@ The second way to specify disjunctions is to choose `chooseSpec`, where the two
824824
type, but are distinguished logically by the two input specifications. The type of
825825
`chooseSpec` is as follows, where the `Int` determines the frequency of each choice.
826826

827-
```
828-
chooseSpec:: HasSpec a => (Int, Specification a) -> (Int, Specification a) -> Specification a
827+
```haskell
828+
chooseSpec :: HasSpec a => (Int, Specification a) -> (Int, Specification a) -> Specification a
829829
```
830830

831831
Here is an example.
832832

833-
```
833+
```haskell
834834
ex12 :: Specification (Int,[Int])
835835
ex12 = chooseSpec
836836
(5, constrained $ \ pair ->
@@ -871,7 +871,7 @@ defined interms of the un-primed function and `match`, and the second defined nt
871871

872872
The primed version of `forAll` is `forAll'`
873873

874-
```
874+
```haskell
875875
ex13a :: Specification [(Int,Int)]
876876
ex13a = constrained $ \ xs ->
877877
forAll xs $ \ x -> match x $ \ a b -> a ==. negate b
@@ -883,7 +883,7 @@ ex13b = constrained $ \ xs ->
883883

884884
The primed version of `constrained` is `constrained'`
885885

886-
```
886+
```haskell
887887
ex14a :: Specification (Int,Int,Int)
888888
ex14a = constrained $ \ triple ->
889889
match triple $ \ a b c -> [ b ==. a + lit 1, c ==. b + lit 1]
@@ -895,7 +895,7 @@ ex14b = constrained' $ \ a b c -> [ b ==. a + lit 1, c ==. b + lit 1]
895895
The primed version of `reify` is `reify'`
896896

897897

898-
```
898+
```haskell
899899
ex15a :: Specification (Int,Int,Int)
900900
ex15a = constrained $ \ triple ->
901901
match triple $ \ x1 x2 x3 ->
@@ -918,7 +918,7 @@ In Haskell we can define data types with multiple constructors, and constructors
918918
The library functions `onCon`, `sel`, and `isJust`, allow us to constrain such types in a way less verbose
919919
than using the `caseOn` library function. Consider the following
920920

921-
```
921+
```haskell
922922
ex16 :: Specification Three
923923
ex16 = constrained $ \ three ->
924924
caseOn three
@@ -935,7 +935,7 @@ This requires that the GHC language directive`{-# LANGUAGE DataKinds #-}` be in
935935
Then apply it to a Term with the type returned by that constructor, followed by a Haskell function with one parameter
936936
for each subcomponent of that constructor, that returns a Pred. Here is `ex16` redone using three `onCon` predicates.
937937

938-
```
938+
```haskell
939939
ex17:: Specification Three
940940
ex17 = constrained $ \ three ->
941941
[ onCon @"One" three (\ x -> x==. lit 1)
@@ -948,21 +948,21 @@ The real power of `onCon` is when you only want to constrain one (or a subset) o
948948
and the other constructors remain unconstrained. Here we only constrain the constructor `Three` and the constructors
949949
`One` and `Two` remain unconstrained.
950950

951-
```
951+
```haskell
952952
ex18:: Specification Three
953953
ex18 = constrained $ \ three ->
954954
onCon @"Three" three ( \ x -> x==. lit 3)
955955
```
956956

957957
Here is another example where we only constrain the constructor `Just` of the maybe type.
958-
```
958+
```haskell
959959
ex19 :: Specification (Maybe Bool)
960960
ex19 = constrained $ \ mb -> onCon @"Just" mb (\ x -> x==. lit False)
961961
```
962962

963963
Haskell allows the definition of data types with named selectors. Here is an example.
964964

965-
```
965+
```haskell
966966
data Dimensions
967967
where Dimensions ::
968968
{ length :: Int
@@ -975,7 +975,7 @@ instance HasSpec Dimensions
975975

976976
This introduces Haskell functions with types
977977

978-
```
978+
```haskell
979979
length :: Dimensions -> Int
980980
width :: Dimensions -> Int
981981
depth :: Dimensions -> Int
@@ -986,14 +986,14 @@ instances, the we can use the `sel` library function to create lifted versions o
986986
the Haskell selector functions like this. Nothe that the lifted `width` uses the trailing
987987
under score convention: `width_` because it manipulates `Term`s not values.
988988

989-
```
989+
```haskell
990990
width_ :: Term Dimensions -> Term Int
991991
width_ d = sel @1 d
992992
```
993993

994994
This requires the `DataKinds` directive, and importing `GHC.Generics` and `GHC.TypeLits` to work.
995995

996-
```
996+
```haskell
997997
{-# LANGUAGE DataKinds #-}
998998
import GHC.Generics
999999
import GHC.TypeLits
@@ -1003,15 +1003,15 @@ When we type-apply the library function `sel` to a type-level `Natural` number l
10031003
selects the `ith` selector function. The selectors are numbered from `0` to `n-1` . Selection
10041004
can always be expressed using `match` like this:
10051005

1006-
```
1006+
```haskell
10071007
ex20a :: Specification Dimensions
10081008
ex20a = constrained $ \ d ->
10091009
match d $ \ l w d -> [ l >. lit 10, w ==. lit 5, d <. lit 20]
10101010
```
10111011

10121012
which can be reexpressed using `sel` as this.
10131013

1014-
```
1014+
```haskell
10151015
ex20b :: Specification Dimensions
10161016
ex20b = constrained $ \ d ->
10171017
[sel @0 d >. lit 10
@@ -1022,7 +1022,7 @@ ex20b = constrained $ \ d ->
10221022
When we wish to constrain just a subset of the subcomponents, selectors make it possible
10231023
to write more concise `Specification`s.
10241024

1025-
```
1025+
```haskell
10261026
ex21 :: Specification Dimensions
10271027
ex21 = constrained $ \ d -> width_ d ==. lit 1
10281028
```
@@ -1038,7 +1038,7 @@ Term level names that were assigned to the Haskell variables. This means the err
10381038
understand. For example consider the over constrained specification. It is over constrained because
10391039
`left` cannot be simultaneously equal to `right` and `right + lit 1`
10401040

1041-
```
1041+
```haskell
10421042
ex22a :: Specification (Int,Int)
10431043
ex22a = constrained $ \ pair ->
10441044
match pair $ \ left right ->
@@ -1061,14 +1061,14 @@ Note the error message is in terms of the internal Term name `v1`. Which is not
10611061

10621062
To make error messages clearer we can name Haskell lambda bound variables using `[var|left|]` instead of just `left`. In order to do this we must have the following directives in our file.
10631063

1064-
```
1064+
```haskell
10651065
{-# LANGUAGE QuasiQuotes #-}
10661066
{-# LANGUAGE ViewPatterns #-}
10671067
```
10681068

10691069
Here is the same example using this naming schema.
10701070

1071-
```
1071+
```haskell
10721072
ex22b :: Specification (Int,Int)
10731073
ex22b = constrained $ \ [var|pair|] ->
10741074
match pair $ \ [var|left|] [var|right|] -> [ left ==. right, left ==. right + lit 1]
@@ -1099,7 +1099,7 @@ another internal number `y`, such that, `x` is equal to `y + y + 1`
10991099

11001100
Here is an example.
11011101

1102-
```
1102+
```haskell
11031103
ex22 :: Specification Int
11041104
ex22 = constrained $ \ [var|oddx|] ->
11051105
unsafeExists
@@ -1114,7 +1114,7 @@ that tells how to compute the hidden variable from the values returned by solvin
11141114
The second is the normal use of a Haskell lambda expression to introduce a Term variable
11151115
naming the hidden variable. Here is an example.
11161116

1117-
```
1117+
```haskell
11181118
ex23 :: Specification Int
11191119
ex23 = ExplainSpec ["odd via (y+y+1)"] $
11201120
constrained $ \ [var|oddx|] ->
@@ -1150,15 +1150,15 @@ If one has a term `x` with type `(Term Bool)` one could use the value of this te
11501150
define a Specification conditional on this term by using the `(caseOn x ...)` library function.
11511151
There are two more concise library function one can use instead.
11521152

1153-
```
1153+
```haskell
11541154
whenTrue :: IsPred p => Term Bool -> p -> Pred
11551155
ifElse :: (IsPred p, IsPred q) => Term Bool -> p -> q -> Pred
11561156
```
11571157

11581158
For example consider the data type `Rectangle` where the selector `square` indicates
11591159
that the rectangle has equal length width and length.
11601160

1161-
```
1161+
```haskell
11621162
data Rectangle = Rectangle { wid :: Int, len :: Int, square :: Bool}
11631163
deriving (Show, Eq,Generic)
11641164
instance HasSimpleRep Rectangle
@@ -1167,7 +1167,7 @@ instance HasSpec Rectangle
11671167

11681168
We can enforce this in a specification as follows.
11691169

1170-
```
1170+
```haskell
11711171
ex26 :: Specification Rectangle
11721172
ex26 = constrained' $ \ wid len square ->
11731173
[ assert $ wid >=. lit 0
@@ -1180,7 +1180,7 @@ Note that there are no constraints relating `wid` and `len` if the selector `squ
11801180
The library function `ifElse` allows two separate sets of constraints, one when the
11811181
`square` is `True` and a completely separate set when `square` is `False`
11821182

1183-
```
1183+
```haskell
11841184
ex27 :: Specification Rectangle
11851185
ex27 = constrained' $ \ wid len square ->
11861186
ifElse square
@@ -1197,15 +1197,15 @@ ex27 = constrained' $ \ wid len square ->
11971197
Explanations allow the writer of a specification to add textual message, that can be used
11981198
if solving a specification fails. These library functions have type
11991199

1200-
```
1200+
```haskell
12011201
explanation :: NonEmpty String -> Pred -> Pred
12021202
assertExplain :: IsPred p => NonEmpty String -> p -> Pred
12031203
ExplainSpec :: [String] -> Specification a -> Specification a
12041204
```
12051205

12061206
Here is a specification with no explanations
12071207

1208-
```
1208+
```haskell
12091209
ex28a :: Specification (Set Int)
12101210
ex28a = constrained $ \ s ->
12111211
[ assert $ member_ (lit 5) s
@@ -1224,7 +1224,7 @@ While combining 2 SetSpecs
12241224

12251225
By adding an `ExplainSpec` like this
12261226

1227-
```
1227+
```haskell
12281228
ex28b :: Specification (Set Int)
12291229
ex28b = ExplainSpec ["5 must be in the set"] $
12301230
constrained $ \ s ->
@@ -1245,7 +1245,7 @@ While combining 2 SetSpecs
12451245
(SetSpec must=[ 5 ] elem=TrueSpec @(Int) size=TrueSpec @(Integer))
12461246
```
12471247

1248-
```
1248+
```haskell
12491249
ex28c :: Specification (Set Int)
12501250
ex28c =
12511251
constrained $ \ s -> explanation (pure "5 must be in the set")
@@ -1272,7 +1272,7 @@ There are a number of library functions that create specifications directly
12721272
and do not use the `constrained` library function. These are particulary useful
12731273
in conjunction with the library function `satisfies` which converts a `Specification` into a `Pred`
12741274

1275-
```
1275+
```haskell
12761276
satisfies :: HasSpec a => Term a -> Specification a -> Pred
12771277
equalSpec :: a -> Specification a
12781278
notEqualSpec :: HasSpec a => a -> Specification a
@@ -1286,7 +1286,7 @@ cardinality :: (Number Integer, HasSpec a) => Specification a -> Specification I
12861286

12871287
Here is an example of the use of `satisfies` in conjunction with `notMemberSpec`
12881288

1289-
```
1289+
```haskell
12901290
ex29 :: Specification Int
12911291
ex29 = constrained $ \ x ->
12921292
[ assert $ x >=. lit 0

0 commit comments

Comments
 (0)