-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make next minor release: ps-0.13.x-v0.27.3 (#542)
* Link to left recursion problem * Fix unification error in MaybeT/ExceptT usage examples * Link to other post on church encoding * Add more chars to list of possible symbols used for infix notation * Recommend quickCheckGen over plain quickCheck test runner
- Loading branch information
1 parent
93dc977
commit 2c4089d
Showing
6 changed files
with
96 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 71 additions & 2 deletions
73
...llo-World/07-Testing/test/02-Quick-Check-and-Laws/07-Problems-with-Arbitrary.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,74 @@ | ||
# Problems with Arbitrary | ||
|
||
Unfortunately, `Arbitrary` often comes with a problem: overlapping instances / orphan instances. | ||
In the examples so far, we have shown you how to run your tests using `Arbitrary`. The downside of `Arbitrary` is that you might want to generate a slightly different value for the same type. This approach will quickly run afoul of two problems. Both problems can be resolved by defining a newtype over the original type and an instance that differs from the original instance: | ||
- the problem of Overlapping Instances | ||
- the problem of Orphan Instances | ||
|
||
For more context and why these issus are bad, read to `FP Philosophical Foundations/Type Clases.md#Type Class Instances: Global vs Local` or read the beginning part of [Avoid overlapping instances with closed type families](https://kseo.github.io/posts/2017-02-05-avoid-overlapping-instances-with-closed-type-families.html). | ||
We will provide two brief examples showing this problem below. For more context and why these two problems are bad, read to `FP Philosophical Foundations/Type Clases.md#Type Class Instances: Global vs Local` or read the beginning part of [Avoid overlapping instances with closed type families](https://kseo.github.io/posts/2017-02-05-avoid-overlapping-instances-with-closed-type-families.html). | ||
|
||
**The Problem of Overlapping Instances**: | ||
```purescript | ||
newtype MyRec = MyRec { a :: String, b :: Int } | ||
instance arbitraryMyRec :: Arbitrary MyRec where | ||
arbitrary = do | ||
a <- genString | ||
b <- chooseInt 1 100 | ||
pure $ MyRec { a, b } | ||
newtype MyRecVariation = MyRecVariation MyRec | ||
instance arbitraryMyRecVariation :: Arbitrary MyRecVariation where | ||
arbitrary = do | ||
a <- map (\str -> str <> " and more") genString | ||
b <- chooseInt 1 200 | ||
pure $ MyRecVariation { a, b } | ||
main :: Effect Unit | ||
main = do | ||
quickCheck \(MyRec r) -> length r.a == r.b | ||
quickCheck \(MyRecVariation r) -> ((length r.a) * 2) == r.b | ||
``` | ||
|
||
**The Problem of Orphan Instances.** Another problem you might experience is that a library has defined a type and its `Arbitrary` instance. However, their version of the instance isn't the implementation you want. Since the `Arbitrary` type class and the type you wish to use were both defined in modules you can't control, you can't define an instance for that type. Thus, you must use resort to the newtype solution. | ||
|
||
Fortunately, quickcheck provides a way around this: we don't have to use `Arbitrary` to generate a value/test. Rather, we can use plain `Gen`: | ||
|
||
| Description | Uses `Arbitrary` | Uses `Gen` | | ||
| - | - | - | | ||
| Run a test 100 times | [quickCheck](https://pursuit.purescript.org/packages/purescript-quickcheck/docs/Test.QuickCheck#v:quickCheck) | [quickCheckGen](https://pursuit.purescript.org/packages/purescript-quickcheck/docs/Test.QuickCheck#v:quickCheckGen) | | ||
| Run a test a specified number of times | [quickCheck'](https://pursuit.purescript.org/packages/purescript-quickcheck/docs/Test.QuickCheck#v:quickCheck') | [quickCheckGen'](https://pursuit.purescript.org/packages/purescript-quickcheck/docs/Test.QuickCheck#v:quickCheckGen') | | ||
| Run a test a specified number of times with access to the seed | [quickCheckWithSeed](https://pursuit.purescript.org/packages/purescript-quickcheck/docs/Test.QuickCheck#v:quickCheckWithSeed) | [quickCheckGenWithSeed](https://pursuit.purescript.org/packages/purescript-quickcheck/docs/Test.QuickCheck#v:quickCheckGenWithSeed) | | ||
| Run a test a specified number of times with access to the seed, returning all the results of the test as a list | [quickCheckPure](https://pursuit.purescript.org/packages/purescript-quickcheck/docs/Test.QuickCheck#v:quickCheckPure) | [quickCheckGenPure](https://pursuit.purescript.org/packages/purescript-quickcheck/docs/Test.QuickCheck#v:quickCheckGenPure) | | ||
| Run a test a specified number of times with access to the seed, returning all the results of the test as a list, including the seed used when running a particular test | [quickCheckPure'](https://pursuit.purescript.org/packages/purescript-quickcheck/docs/Test.QuickCheck#v:quickCheckPure') | [quickCheckGenPure'](https://pursuit.purescript.org/packages/purescript-quickcheck/docs/Test.QuickCheck#v:quickCheckGenPure') | | ||
|
||
Thus, we could rewrite our above example test to... | ||
```purescript | ||
newtype MyRec = MyRec { a :: String, b :: Int } | ||
genMyRec :: Gen MyRec | ||
genMyRec = do | ||
a <- genString | ||
b <- chooseInt 1 100 | ||
pure $ MyRec { a, b } | ||
genMyRecVariation :: Gen MyRec | ||
genMyRecVariation = do | ||
a <- map (\str -> str <> " and more") genString | ||
b <- chooseInt 1 200 | ||
pure $ MyRecVariation { a, b } | ||
main :: Effect Unit | ||
main = do | ||
quickCheckGen do | ||
(MyRec r) <- genMyRec | ||
pure $ length r.a == r.b | ||
quickCheckGen do | ||
(MyRecVariation r) <- genMyRecVariation | ||
pure $ ((length r.a) * 2) == r.b | ||
-- or just inline `genMyRecVariation` and its test | ||
quickCheckGen do | ||
a <- map (\str -> str <> " and more") genString | ||
b <- chooseInt 1 200 | ||
pure $ length a == b | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# Church Encoding | ||
|
||
See [Scrap Your Constructors: Church Encoding Algebraic Types](https://programmable.computer/posts/church_encoding.html) | ||
See these links: | ||
- [Scrap Your Constructors: Church Encoding Algebraic Types](https://programmable.computer/posts/church_encoding.html) | ||
- [The visitor pattern is essentially the same thing as Church encoding ](https://www.haskellforall.com/2021/01/the-visitor-pattern-is-essentially-same.html) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Parsing | ||
|
||
This file will store various links related to parsing. | ||
|
||
## Left Recursion Problem | ||
|
||
See https://github.com/glebec/left-recursion for a clear explanation of this problem and its solution |