packages feed

type-spec-0.2.0.0: README.md

[![Build Status](https://travis-ci.org/sheyll/type-spec.svg?branch=master)](https://travis-ci.org/sheyll/type-spec)

[![Hackage](https://img.shields.io/badge/type-spec-green.svg?style=flat)](http://hackage.haskell.org/package/type-spec)


# A tiny EDSL to write type-level-unit tests.


A small example:

    import Test.TypeSpec

    main :: IO ()
    main = print spec0

    spec :: Expect (Int `Isn't` Bool)
    spec = Valid

This will output:

    Valid:
         • Type:  Int
           differs from:  Bool

Using the operators from _TypeSpecCrazy_:

    specCrazy ::

        "Higher kinded assertions"
       ###########################

       "ShouldBe accepts types of kind * -> *"
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

           ShouldBe  Maybe Maybe
        -* ShouldBe  []    []
        -* ShouldBe  (->)  (->)

    specCrazy = Valid
    main = print specCrazy

The output:

    Valid:
         Higher kinded assertions
           ShouldBe accepts types of kind * -> *
             • Types are equal
             • Types are equal
             • Types are equal

If you like Lisp, this might be for you:

    type ALot = 1000

    specAliases ::
      (Explain "There are a variety aliases for the basic combinators."
        (Context "Basic Combinators"
          (Describe "Context"
            (It "labels expectations using 'It'"
              (Describe "Describe"
                (It's "an alias for It, just like They"
                  (It's "time for the first assertion"
                    (1000 `Is` ALot))))))))
    specAliases = Valid

    main = print specAliases

This will output:

    Valid:
         There are a variety aliases for the basic combinators.
           Basic Combinators
             Context
               Labels expectations using 'It'
                 Describe
                   is an alias for It, just like They
                     is time for the first assertion
                       • Types are equal

The key feature is that the compiler checks the assertions and expectations made
in a 'TypeSpec' and right away rejects invalid types.

When compiling this example:

    specFailing ::
        TypeSpec
            (It "counts the number of elements in a tuple"
                (Count ((),(),()) `ShouldBe` 4))
    specFailing = Valid

    type family Count a :: Nat where
      Count (a,b) = 2
      Count (a,b,c) = 3
      Count (a,b,c,d) = 4

The compiler complains:

    error:
       • counts the number of elements in a tuple
             Expected type: 3
             Actual type:   4
       • In the expression: Valid
         In an equation for ‘specFailing’: specFailing = Valid


After all, with `TypeError` GHC is quite a test-runner.

If you accept to defer type checking and have invalid specs checked during test execution, use
(should-not-typecheck)[https://github.com/CRogers/should-not-typecheck].