packages feed

speculate-0.2.8: README.md

Speculate
=========

[![Speculate Build Status][build-status]][build-log]
[![Speculate on Hackage][hackage-version]][speculate-on-hackage]
[![Speculate on Stackage LTS][stackage-lts-badge]][speculate-on-stackage-lts]
[![Speculate on Stackage Nightly][stackage-nightly-badge]][speculate-on-stackage-nightly]

Speculate automatically discovers laws about [Haskell] functions.
Give Speculate a bunch of Haskell functions and it will discover laws like:

  * equations, such as `id x == x`;
  * inequalities, such as `0 <= x * x`;
  * conditional equations, such as `x <= 0  ==>  x + abs x == 0`.

Speculate is similar to, and inspired by, [QuickSpec].


Installing Speculate
--------------------

To install the [latest Speculate version from Hackage], just:

	$ cabal update
	$ cabal install speculate

Pre-requisites are [cmdargs] and [leancheck].
They should be automatically resolved and installed by [Cabal].


Using Speculate
---------------

Speculate is used as a library: import it, then call the function [`speculate`]
with relevant arguments.  The following program Speculates about the
functions [`(+)`] and [`abs`]:

	import Test.Speculate

	main :: IO ()
	main = speculate args
	  { constants =
	      [ showConstant (0::Int)
	      , showConstant (1::Int)
	      , constant "+"   ((+)  :: Int -> Int -> Int)
	      , constant "abs" (abs  :: Int -> Int)
	      ]
	  }

when run, it prints the following:

	_ :: Int  (holes: Int)
	0 :: Int
	1 :: Int
	(+) :: Int -> Int -> Int
	abs :: Int -> Int

	    abs (abs x) == abs x
	          x + 0 == x
	          x + y == y + x
	    (x + y) + z == x + (y + z)
	abs (x + abs x) == x + abs x
	  abs x + abs x == abs (x + x)
	abs (1 + abs x) == 1 + abs x

	x <= abs x
	0 <= abs x
	x <= x + 1


Now, if we add [`<=`] and [`<`] as background constants on [`args`]

	  , constants =
	      [ showConstant (0::Int)
	      , showConstant (1::Int)
	      , constant "+"   ((+)  :: Int -> Int -> Int)
	      , constant "abs" (abs  :: Int -> Int)
	      , background
	      , constant "<="  ((<=) :: Int -> Int -> Bool)
	      , constant "<"   ((<)  :: Int -> Int -> Bool)
	      ]

then run again, we get the following as well:

	    y <= x ==> abs (x + abs y) == x + abs y
	    x <= 0 ==>       x + abs x == 0
	abs x <= y ==>     abs (x + y) == x + y
	abs y <= x ==>     abs (x + y) == x + y

For more examples, see the [eg](eg) folder.


Similarities and Differences to QuickSpec
-----------------------------------------

Speculate is inspired by [QuickSpec].
Like QuickSpec, Speculate uses testing to speculate equational laws about given
Haskell functions.  There are some differences:

|                   | Speculate                 | QuickSpec                         |
| ----------------: | ------------------------- | --------------------------------- |
| testing           | enumerative ([LeanCheck]) | random ([QuickCheck])             |
| equational laws   | yes (after completion)    | yes (as discovered)               |
| inequational laws | yes                       | no                                |
| conditional laws  | yes                       | restricted to a set of predicates |
| polymorphism      | no                        | yes                               |
| performance       | slower                    | faster                            |

For most examples, Speculate runs slower than QuickSpec 2 but faster than QuickSpec 1.


More documentation
------------------

For more examples, see the [eg](eg) and [bench](bench) folders.

Speculate has been subject to a paper, see the
[Speculate Paper on Haskell Symposium 2017](https://matela.com.br/paper/speculate.pdf).

[leancheck]: https://hackage.haskell.org/package/leancheck
[LeanCheck]: https://hackage.haskell.org/package/leancheck
[QuickSpec]: https://github.com/nick8325/quickspec
[QuickCheck]: https://hackage.haskell.org/package/QuickCheck
[cmdargs]: https://hackage.haskell.org/package/cmdargs

[Cabal]:   https://www.haskell.org/cabal
[Haskell]: https://www.haskell.org/

[`speculate`]: https://hackage.haskell.org/package/speculate/docs/Test-Speculate.html#v:speculate
[`args`]:      https://hackage.haskell.org/package/speculate/docs/Test-Speculate.html#v:args
[`constant`]:  https://hackage.haskell.org/package/speculate/docs/Test-Speculate.html#v:constant

[`(+)`]:       https://hackage.haskell.org/package/base/docs/Prelude.html#v:-43-
[`abs`]:       https://hackage.haskell.org/package/base/docs/Prelude.html#v:abs
[`<=`]:        https://hackage.haskell.org/package/base/docs/Prelude.html#v:-60--61-
[`<`]:         https://hackage.haskell.org/package/base/docs/Prelude.html#v:-60-

[build-status]: https://travis-ci.org/rudymatela/speculate.svg?branch=master
[build-log]:    https://travis-ci.org/rudymatela/speculate
[hackage-version]: https://img.shields.io/hackage/v/speculate.svg
[latest Speculate version from Hackage]: https://hackage.haskell.org/package/speculate
[speculate-on-hackage]:                  https://hackage.haskell.org/package/speculate
[stackage-lts-badge]:            http://stackage.org/package/speculate/badge/lts
[stackage-nightly-badge]:        http://stackage.org/package/speculate/badge/nightly
[speculate-on-stackage]:         http://stackage.org/package/speculate
[speculate-on-stackage-lts]:     http://stackage.org/lts/package/speculate
[speculate-on-stackage-nightly]: http://stackage.org/nightly/package/speculate