type-spec 0.1.0.0 → 0.2.0.0
raw patch · 15 files changed
+627/−219 lines, 15 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Test.TypeSpec.Group: type (-*) expectation1 expectation2 = expectation1 -/- expectation2
- Test.TypeSpec.Internal.Apply: type TyFunData a b = TyFun a b -> Type
+ Test.TypeSpec: type Not = ShouldBeTrue
+ Test.TypeSpec: type That = ShouldBeTrue
- Test.TypeSpec.Internal.Apply: data Const' :: a -> (TyFunData b a)
+ Test.TypeSpec.Internal.Apply: data Const' :: a -> (b ~> a)
- Test.TypeSpec.Internal.Apply: data Const'' :: TyFunData a (TyFunData b a)
+ Test.TypeSpec.Internal.Apply: data Const'' :: a ~> (b ~> a)
Files
- .travis.yml +24/−0
- README.md +110/−0
- examples/Main.hs +35/−1
- src/Test/TypeSpec.hs +94/−27
- src/Test/TypeSpec/Core.hs +7/−8
- src/Test/TypeSpec/Group.hs +14/−18
- src/Test/TypeSpec/Internal/Apply.hs +8/−41
- src/Test/TypeSpec/Internal/Either.hs +5/−2
- src/Test/TypeSpec/Internal/Equality.hs +9/−4
- src/Test/TypeSpec/Internal/Result.hs +19/−10
- src/Test/TypeSpec/Label.hs +1/−1
- src/Test/TypeSpec/ShouldBe.hs +8/−10
- src/Test/TypeSpecCrazy.hs +219/−93
- stack.yaml +67/−0
- type-spec.cabal +7/−4
+ .travis.yml view
@@ -0,0 +1,24 @@+language: c++sudo: false+cache:+ directories:+ - $HOME/.stack/++matrix:+ include:+ - env: CABALVER=1.22 GHCVER=8.0.1+ addons: {apt: {packages: [cabal-install-1.22,ghc-8.0.1],sources: [hvr-ghc]}}++before_install:+ - mkdir -p ~/.local/bin+ - export PATH=~/.local/bin:$PATH+ - travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar -xzO --wildcards '*/stack' > ~/.local/bin/stack+ - chmod a+x ~/.local/bin/stack++install:+ - stack -j 2 setup --no-terminal --resolver nightly+ - stack -j 2 build --only-snapshot --no-terminal++script:+ - stack -j 2 test --no-terminal
+ README.md view
@@ -0,0 +1,110 @@++[](https://travis-ci.org/sheyll/type-spec)++[](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].
examples/Main.hs view
@@ -1,7 +1,6 @@ -- | Some examples for 'Test.TypeSpec' module Main where -import Data.Kind import GHC.TypeLits import Test.TypeSpecCrazy @@ -15,6 +14,7 @@ print spec1 print specCrazy print specInvalidCrazy+ print specCrazyMoreNested -- * TypeSpec Examples @@ -155,3 +155,37 @@ specInvalidCrazy :: SpecInvalidCrazy specInvalidCrazy = Invalid+++specCrazyMoreNested ::++ "Title"+ ######++ "Top-level "+ ~~~~~~~~~~~~++ "Nested:"+ ~~~~~~~~~+ Int `Is` Int+ -*-+ Int `Is` Int+ -*-+ Int `Is` Int++ -/-++ "Top-level "+ ~~~~~~~~~~~~++ "Nested:"+ ~~~~~~~~~+ Int `Is` Int+ -*-+ "Nested:"+ ~~~~~~~~~+ Int `Is` Int+ -*-+ Int `Is` Int++specCrazyMoreNested = Valid
src/Test/TypeSpec.hs view
@@ -1,37 +1,102 @@--- | A tiny EDSL to write type-level-unit tests.+{-|+Module : Test.TypeSpec+Description : Type-Level eDSL for Type-Unit-Tests+Copyright : (c) Sven Heyll, 2016+License : BSD-3+Maintainer : sven.heyll@gmail.com+Stability : experimental++A tiny EDSL to write type-level-unit tests.++A simple example:++> specHelloWorld :: Expect (Int `Isn't` Bool)+> specHelloWorld = Valid++We can also /expect/ a bit more using lists and tuples:++> specGrouped+> :: Expect '[ Int `Isn't` Bool+> , Int `Is` Int+> , Bool `Is` Bool `ButNot` String+> ]+> specGrouped = Valid++The expectations are /executed/ by the compiler when solving the constraints of+'TypeSpec's constructors.++A 'TypeSpec' also has a 'Show' instance, which can be used in real unit tests+to print the expectations.++ This module contains mainly re-exports of.++ * "Test.TypeSpec.Core"++ * "Test.TypeSpec.Group"++ * "Test.TypeSpec.Label"++ * "Test.TypeSpec.ShouldBe"++-} module Test.TypeSpec- ( type Expect- , type Explain- , type It's- , type IsTheSameAs- , type Is- , type TheseAreEqual- , type IsNot- , type Isn't- , type IsNotTheSameAs- , type IsDifferentFrom- , type TheseAreNotEqual- , type IsTrue- , type Therefore- , type And- , type IsFalse- , type They- , type Describe- , type Context- , module ReExport)+ (+ -- * 'TypeSpec' Aliases++ type Expect,+ type Explain,++ -- * 'ShouldBe' aliases++ type Is,+ type IsTheSameAs,+ type TheseAreEqual,++ -- * 'ShouldNotBe' aliases++ type IsNot,+ type Isn't,+ type IsNotTheSameAs,+ type IsDifferentFrom,+ type TheseAreNotEqual,++ -- * 'ShouldBeTrue' aliases++ type IsTrue,+ type And,+ type Therefore,+ type That,++ -- * 'ShouldBeFalse' aliases++ type IsFalse,+ type Not,++ -- * Labelling Aliases++ type They,+ type Describe,+ type Context,+ type It's,++ -- * Reexports++ module Test.TypeSpec.Core,+ module Test.TypeSpec.Group,+ module Test.TypeSpec.Label,+ module Test.TypeSpec.ShouldBe++ ) where -import Test.TypeSpec.Core as ReExport-import Test.TypeSpec.Group as ReExport-import Test.TypeSpec.Label as ReExport-import Test.TypeSpec.ShouldBe as ReExport+import Test.TypeSpec.Core+import Test.TypeSpec.Group+import Test.TypeSpec.Label+import Test.TypeSpec.ShouldBe -- * 'TypeSpec' Aliases --- | An alias for 'TypeSpec'. type Expect = TypeSpec---- | Another alias for 'TypeSpec' (and also 'It') type Explain does this = TypeSpec (It does this) -- * 'ShouldBe' aliases@@ -53,10 +118,12 @@ type IsTrue = ShouldBeTrue type And = ShouldBeTrue type Therefore = ShouldBeTrue+type That = ShouldBeTrue -- * 'ShouldBeFalse' aliases type IsFalse = ShouldBeFalse+type Not = ShouldBeTrue -- * Labelling Aliases
src/Test/TypeSpec/Core.hs view
@@ -1,7 +1,11 @@ -- | Core of the TypeSpec abstractions. Import to add custom instances. module Test.TypeSpec.Core- ( TypeSpec (..)+ (+ -- * Core Data Type+ TypeSpec (..)+ -- * Expectations , type EvalExpectation+ -- * Pretty Printing Support , PrettyTypeSpec(..) , prettyIndentation , nest'@@ -16,8 +20,8 @@ import Test.TypeSpec.Internal.Result as ReExport import Text.PrettyPrint --- * Type Level Specifcations + -- | A type specification. data TypeSpec expectation where -- | Expect the given expectations to hold. If the compiler does not reject it -@@ -29,8 +33,6 @@ Invalid :: (DontTry (EvalExpectation expectation)) => TypeSpec expectation --- * Expectations- -- | An open family of type level expectation evaluators, that return either @()@ -- or an @ErrorMessage@. type family EvalExpectation (expectation :: k) :: Result k@@ -48,14 +50,11 @@ type instance EvalExpectation (expectation ': rest) = Cons'' <$> EvalExpectation expectation <*> EvalExpectation rest --- * Pretty Printing -- | A class for pretty printing via the 'Show' instance of 'TypeSpec'. class PrettyTypeSpec (t :: k) where prettyTypeSpec :: proxy t -> Doc --- * Printing/Showing- instance PrettyTypeSpec t => Show (TypeSpec t) where show px@Valid = render@@ -86,7 +85,7 @@ => PrettyTypeSpec '(expectation1, expectation2) where prettyTypeSpec _ =- prettyTypeSpec pe1 $+$ prettyTypeSpec pe2 + prettyTypeSpec pe1 $+$ prettyTypeSpec pe2 where pe1 = Proxy :: Proxy expectation1 pe2 = Proxy :: Proxy expectation2
src/Test/TypeSpec/Group.hs view
@@ -1,6 +1,6 @@--- | Group expectations+-- | Composed Expectations. module Test.TypeSpec.Group- ( type (-/-), type (-*) )+ ( type (-/-) ) where import Data.Proxy@@ -9,34 +9,30 @@ import Test.TypeSpec.Internal.Either () import Text.PrettyPrint --- * Composed Expectations+{-| Combine two expectations. --- | A @cons@ like operator.--- Make a list of expectations. Use this to chain together any expectations--- especially those using '(~~~)' or '(-*)', since it has a lower precedence--- than both.+Make a collection of expectations:++> (2 + 2) `Is` 4+> -/-+> (4 + 4) `Is` 8+> -/-+> 'True `IsNot` 'False+-} data expectation1 -/- expectation2 infixr 1 -/- type instance EvalExpectation (expectation -/- expectations) =- TyCon2 ((-/-)) <$> EvalExpectation expectation <*> EvalExpectation expectations---- | A @cons@ like operator.--- Make a list of expectations. Use this to chain together anything /below/ or--- inside '(-/-)' and '(~~~)' parts. The precedence of this operator is higher--- that that of '(-/-)'.-type expectation1 -* expectation2 = expectation1 -/- expectation2-infixr 3 -*---- * Pretty Printing Instances+ TyCon2 (-/-) <$> EvalExpectation expectation <*> EvalExpectation expectations +-- | Pretty Printing Instance. instance ( PrettyTypeSpec expectation1 , PrettyTypeSpec expectation2 ) => PrettyTypeSpec (expectation1 -/- expectation2) where prettyTypeSpec _ =- (prettyTypeSpec pe1) $+$ (prettyTypeSpec pe2)+ prettyTypeSpec pe1 $+$ prettyTypeSpec pe2 where pe1 = Proxy :: Proxy expectation1 pe2 = Proxy :: Proxy expectation2
src/Test/TypeSpec/Internal/Apply.hs view
@@ -1,42 +1,14 @@ -- | Useful abstractions for type level programming using. This reimplements -- parts of the singletons library, which is just too heavy of a dependency to -- carry around, when only three small types are used of it.-module Test.TypeSpec.Internal.Apply- ( type (>>=)- , type (>>)- , type (<*>)- , type (<$>$$)- , type (<$>$)- , type (<$>)- , type TyCon1- , type TyCon2- , type Apply- , TyFun, type TyFunData- , type (~>)- , type Cons''- , type Cons'- , type Pair''- , type Pair'- , type Const- , type Const'- , type Const''- , Flip'- , Flip- , Flip_- , type Flip__- , Compose''- , Compose'- , Compose- , type Compose_- )- where+module Test.TypeSpec.Internal.Apply where import Data.Kind -- | Bind to actions. type family (>>=) (ma :: monad a)- (f :: TyFunData (a :: Type) ((monad b) :: Type))+ (f :: a ~> ((monad b) :: Type)) :: monad b -- | Execute one action and then the next, ignore the result of the first.@@ -48,25 +20,25 @@ (f :: m (a ~> b)) <*> (ma :: m a) :: m b where mf <*> mx = mf >>= Apply (Flip (<$>$$)) mx --- | Tuple construction+-- * Tuple construction data Pair'' :: a ~> b ~> (a, b) data Pair' :: a -> b ~> (a, b) type instance Apply Pair'' x = Pair' x type instance Apply (Pair' x) y = '(x, y) --- | List construction+-- * List construction data Cons'' :: a ~> [a] ~> [a] data Cons' :: a -> [a] ~> [a] type instance Apply Cons'' x = Cons' x type instance Apply (Cons' x) xs = x ': xs --- | Convert data types to Partially applicable type functions+-- * Convert data types to Partially applicable type functions data TyCon1 :: (a -> b) -> a ~> b data TyCon2 :: (a -> b -> c) -> a ~> b ~> c type instance Apply (TyCon1 f) x = f x type instance Apply (TyCon2 f) x = (TyCon1 (f x)) --- | Execute an action and map a pure function over the result.+-- * Execute an action and map a pure function over the result. data (<$>$$) :: (a ~> b) ~> m a ~> m b data (<$>$) :: (a ~> b) -> m a ~> m b type instance Apply (<$>$$) f = (<$>$) f@@ -75,7 +47,6 @@ (f :: (a ~> b)) <$> (ma :: m a) :: m b -- * Flip Type Functions- data Flip' :: (a ~> b ~> c) ~> b ~> a ~> c data Flip :: (a ~> b ~> c) -> b ~> a ~> c data Flip_ :: (a ~> b ~> c) -> b -> a ~> c@@ -87,7 +58,6 @@ Flip__ f y x = Apply (Apply f x) y -- * Type Function composition- data Compose'' :: (b ~> c) ~> (a ~> b) ~> (a ~> c) data Compose' :: (b ~> c) -> (a ~> b) ~> (a ~> c) data Compose :: (b ~> c) -> (a ~> b) -> (a ~> c)@@ -100,17 +70,14 @@ -- * Type-Level 'const'- type family Const (a :: t) (b :: t') :: t where Const a b = a-data Const' :: a -> (TyFunData b a)-data Const'' :: TyFunData a (TyFunData b a)+data Const' :: a -> (b ~> a)+data Const'' :: a ~> (b ~> a) type instance Apply Const'' a = Const' a type instance Apply (Const' a) b = Const a b -- * Defunctionalization- data TyFun :: Type -> Type -> Type-type TyFunData a b = TyFun a b -> Type type a ~> b = TyFun a b -> Type infixr 0 ~> type family Apply (f :: a ~> b) (x :: a) :: b
src/Test/TypeSpec/Internal/Either.hs view
@@ -1,16 +1,19 @@ -- | Useful abstractions for type level programming using 'Either'. module Test.TypeSpec.Internal.Either (type FromLeft) where -import Test.TypeSpec.Internal.Apply +import Test.TypeSpec.Internal.Apply --- * Either instances+-- * Either instances for '>>=' type instance (>>=) ('Right a) f = Apply f a type instance (>>=) ('Left b) f = 'Left b +-- * Either instances for '<$>'+ type instance (<$>) f ('Right a) = 'Right (Apply f a) type instance (<$>) f ('Left a) = 'Left a +-- | Return the left type of a promoted 'Either' type family FromLeft (e :: Either a b) :: a where FromLeft ('Left a) = a
src/Test/TypeSpec/Internal/Equality.hs view
@@ -1,8 +1,13 @@ -- | Type Equality-module Test.TypeSpec.Internal.Equality (type PolyKindEq) where+module Test.TypeSpec.Internal.Equality (type EqExtra) where + import Data.Type.Equality+ -- | Operator 'Data.Equality.(==)' expects both arguments to have the -- same kind.- type family PolyKindEq (a :: ak) (b :: bk) :: Bool where- PolyKindEq a a = 'True- PolyKindEq a b = 'False+ type family EqExtra (a :: ak) (b :: bk) :: Bool where+ EqExtra ('Left x) ('Left y) = EqExtra x y+ EqExtra ('Right x) ('Right y) = EqExtra x y+ EqExtra a a = 'True+ EqExtra (a :: k) (b :: k) = a == b+ EqExtra a b = 'False
src/Test/TypeSpec/Internal/Result.hs view
@@ -1,10 +1,15 @@--- | Result type used in constraints inside 'TypeSpec' to propagate type errors.+-- | A result type used in constraints inside 'TypeSpec' to chain computations+-- that may fail with a 'TypeError'. module Test.TypeSpec.Internal.Result- ( type Result- , type Try- , type DontTry+ (+ -- * Results that with 'TypeErrors'+ type Result , type FAILED , type OK+ -- * Error propagation+ , type Try+ , type DontTry+ -- * Extending Error Messages , type PrependToError ) where @@ -13,18 +18,24 @@ import Test.TypeSpec.Internal.Apply () import Test.TypeSpec.Internal.Either () --- * Type error propagation- -- | When a type level expectation is tested, it might be that compound -- expectations fail. In order to have a small, precise error message, the type -- level assertion results are made to have kind 'Result'. type Result = Either ErrorMessage +-- | A nice alias for 'Left'+type OK = 'Right+-- | A nice alias for 'Right'+type FAILED = 'Left++-- | Return the result or fail with a 'TypeError' type family Try (e :: Result k) :: k where Try (OK (d :: k)) = d Try (FAILED m) = TypeError m +-- | A constraint that is satisfied if the parameter is 'Left'. Fails with a+-- 'TypeError' otherwise. type family DontTry (e :: Result r) :: Constraint where DontTry (FAILED e) = ()@@ -35,10 +46,8 @@ ':$$: 'Text "... turns out it actually is!") --- | A nice name than 'Left'-type OK = 'Right-type FAILED = 'Left-+-- | In case of @'Left' 'ErrorMessage'@ prepend a message to the message, if the+-- parameter was @'Right' x@ just return @'Right' x@. type family PrependToError (message :: ErrorMessage)
src/Test/TypeSpec/Label.hs view
@@ -1,4 +1,4 @@--- | Label expectations+-- | Labels for expectations. module Test.TypeSpec.Label ( It ) where
src/Test/TypeSpec/ShouldBe.hs view
@@ -10,7 +10,7 @@ import Data.Kind import Data.Type.Bool-import Data.Type.Equality+ import Data.Typeable import GHC.TypeLits import Test.TypeSpec.Core@@ -24,7 +24,7 @@ data ShouldBeTrue :: expectation -> Type type instance EvalExpectation (ShouldBeTrue t) =- If (PolyKindEq t 'True)+ If (EqExtra t 'True) (OK (ShouldBeTrue t)) (FAILED ('Text "Should have been 'True: " ':<>: 'ShowType t))@@ -33,7 +33,7 @@ data ShouldBeFalse :: expectation -> Type type instance EvalExpectation (ShouldBeFalse t) =- If (PolyKindEq t 'False)+ If (EqExtra t 'False) (OK (ShouldBeFalse t)) (FAILED ('Text "Should have been 'False: " ':<>: 'ShowType t))@@ -44,8 +44,8 @@ type instance EvalExpectation (ButNot (ShouldBe expected actual) other) =- If (expected == actual)- (If (expected == other)+ If (EqExtra expected actual)+ (If (EqExtra expected other) (FAILED ('Text "Expected type: " ':$$: 'Text " " ':<>: 'ShowType expected@@ -61,7 +61,7 @@ type instance EvalExpectation (ShouldBe expected actual) =- If (PolyKindEq expected actual)+ If (EqExtra expected actual) (OK (ShouldBe expected actual)) (FAILED ('Text "Expected type: " ':<>: 'ShowType expected@@ -72,7 +72,7 @@ type instance EvalExpectation (ShouldNotBe expected actual) =- If (PolyKindEq expected actual)+ If (EqExtra expected actual) (FAILED ('Text "Expected type: " ':$$: 'Text " " ':<>: 'ShowType expected@@ -80,8 +80,6 @@ ':$$: 'Text " " ':<>: 'ShowType actual)) (OK (ShouldNotBe expected actual)) --- * PrettyTypeSpec instances- instance PrettyTypeSpec (ShouldBeTrue a) where prettyTypeSpec _px = prettyBulletPoint $ text "Type == True"@@ -120,4 +118,4 @@ -- | Pretty print a test prefix by a bullet-point. prettyBulletPoint :: Doc -> Doc-prettyBulletPoint doc = text "•" <+> doc +prettyBulletPoint doc = text "•" <+> doc
src/Test/TypeSpecCrazy.hs view
@@ -1,78 +1,83 @@--- | Funny operators that are mere type aliases for the constructs in--- 'TypeSpec'+-- | Funny operators that are mere type aliases for the constructs in 'TypeSpec' module Test.TypeSpecCrazy- ( module Test.TypeSpecCrazy+ (+ -- * Crazy Type operators for 'It'+ type (--*)+ , type (~~~)+ , type (~~~~~~)+ , type (~~~~~~~~~)+ , type (~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ , type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)+ -- * Crazy Type operators for 'TypeSpec'+ , type (###)+ , type (######)+ , type (#########)+ , type (############)+ , type (###############)+ , type (##################)+ , type (#####################)+ , type (########################)+ , type (###########################)+ , type (##############################)+ , type (#################################)+ , type (####################################)+ , type (#######################################)+ , type (##########################################)+ , type (#############################################)+ , type (################################################)+ , type (###################################################)+ , type (######################################################)+ , type (#########################################################)+ , type (############################################################)+ , type (###############################################################)+ , type (##################################################################)+ , type (#####################################################################)+ , type (########################################################################)++ -- * Grouping Aliases+ , type (-*)+ , type (-*-)+ , module ReExport) where import Test.TypeSpec as ReExport --- * Crazy Type operators---- | Create a 'TypeSpec' with an initial description or title followed by some--- expectations. Note that the number of @#@s is alway a multiple of 3.-type (###) title expr = Explain title expr-type (######) title expr = Explain title expr-type (#########) title expr = Explain title expr-type (############) title expr = Explain title expr-type (###############) title expr = Explain title expr-type (##################) title expr = Explain title expr-type (#####################) title expr = Explain title expr-type (########################) title expr = Explain title expr-type (###########################) title expr = Explain title expr-type (##############################) title expr = Explain title expr-type (#################################) title expr = Explain title expr-type (####################################) title expr = Explain title expr-type (#######################################) title expr = Explain title expr-type (##########################################) title expr =- Explain title expr-type (#############################################) title expr =- Explain title expr-type (################################################) title expr =- Explain title expr-type (###################################################) title expr =- Explain title expr-type (######################################################) title expr =- Explain title expr-type (#########################################################) title expr =- Explain title expr-type (############################################################) title expr =- Explain title expr-type (###############################################################) title expr =- Explain title expr-type (##################################################################) title expr =- Explain title expr-type (#####################################################################) title expr =- Explain title expr-type (########################################################################) title expr =- Explain title expr+{-| Alias for 'It', note that the number of @~@s is alway a multiple of 3. This+provides the impression of an underlined title followed by other expectations. -infixr 0 ###-infixr 0 ######-infixr 0 #########-infixr 0 ############-infixr 0 ###############-infixr 0 ##################-infixr 0 #####################-infixr 0 ########################-infixr 0 ###########################-infixr 0 ##############################-infixr 0 #################################-infixr 0 ####################################-infixr 0 #######################################-infixr 0 ##########################################-infixr 0 #############################################-infixr 0 ################################################-infixr 0 ###################################################-infixr 0 ######################################################-infixr 0 #########################################################-infixr 0 ############################################################-infixr 0 ###############################################################-infixr 0 ##################################################################-infixr 0 #####################################################################-infixr 0 ########################################################################+It allows to write the following type: --- | Specify an expectation using an underlined title using 'It'.+>+> type ExpectationWithTitle =+> TypeSpec (+>+> "This is a title for some assertions:"+> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+>+> (2 + 2) `Is` 4+>+> )+ -} type (--*) title expr = It title expr type (~~~) title expr = It title expr type (~~~~~~) title expr = It title expr@@ -110,31 +115,152 @@ type (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~) title expr = It title expr -infixl 2 --*-infixl 2 ~~~-infixr 2 ~~~~~~-infixr 2 ~~~~~~~~~-infixr 2 ~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-infixr 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 --*+infixr 3 ~~~+infixr 3 ~~~~~~+infixr 3 ~~~~~~~~~+infixr 3 ~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+infixr 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +{-| Create a 'TypeSpec' with an initial description or title followed by some+expectations. Note that the number of @#@s is alway a multiple of 3.++It allows to rewrite the example above in a shorter way:++>+> type ExpectationWithTitleShorter =+>+> "This is a title for some assertions:"+> ######################################+>+> (2 + 2) `Is` 4+>++-}+type (###) title expr = Explain title expr+type (######) title expr = Explain title expr+type (#########) title expr = Explain title expr+type (############) title expr = Explain title expr+type (###############) title expr = Explain title expr+type (##################) title expr = Explain title expr+type (#####################) title expr = Explain title expr+type (########################) title expr = Explain title expr+type (###########################) title expr = Explain title expr+type (##############################) title expr = Explain title expr+type (#################################) title expr = Explain title expr+type (####################################) title expr = Explain title expr+type (#######################################) title expr = Explain title expr+type (##########################################) title expr =+ Explain title expr+type (#############################################) title expr =+ Explain title expr+type (################################################) title expr =+ Explain title expr+type (###################################################) title expr =+ Explain title expr+type (######################################################) title expr =+ Explain title expr+type (#########################################################) title expr =+ Explain title expr+type (############################################################) title expr =+ Explain title expr+type (###############################################################) title expr =+ Explain title expr+type (##################################################################) title expr =+ Explain title expr+type (#####################################################################) title expr =+ Explain title expr+type (########################################################################) title expr =+ Explain title expr++infixr 1 ###+infixr 1 ######+infixr 1 #########+infixr 1 ############+infixr 1 ###############+infixr 1 ##################+infixr 1 #####################+infixr 1 ########################+infixr 1 ###########################+infixr 1 ##############################+infixr 1 #################################+infixr 1 ####################################+infixr 1 #######################################+infixr 1 ##########################################+infixr 1 #############################################+infixr 1 ################################################+infixr 1 ###################################################+infixr 1 ######################################################+infixr 1 #########################################################+infixr 1 ############################################################+infixr 1 ###############################################################+infixr 1 ##################################################################+infixr 1 #####################################################################+infixr 1 ########################################################################++{-| Crazy operator alias for '-/-' with higher precedence.++It allows to group expectations more beautiful than using type level lists.++> specCrazyMoreNested ::+>+> "Title"+> ######+>+> "Top-level "+> ~~~~~~~~~~~~+>+> "Nested:"+> ~~~~~~~~~+> Int `Is` Int+> -*-+> Int `Is` Int+> -*-+> Int `Is` Int+>+> -/-+>+> "Top-level "+> ~~~~~~~~~~~~+>+> "Nested:"+> ~~~~~~~~~+> Int `Is` Int+> -*-+> "Nested:"+> ~~~~~~~~~+> Int `Is` Int+> -*-+> Int `Is` Int+>+> specCrazyMoreNested = Valid++-} type expectation1 -*- expectation2 = expectation1 -/- expectation2-infixl 2 -*-+infixr 3 -*-++-- | Crazy operator alias for '-/-'.+--+-- Make a list of expectations. The precedence of this operator is even higher+-- than that of '-*-'.+type expectation1 -* expectation2 = expectation1 -/- expectation2+infixr 4 -*
+ stack.yaml view
@@ -0,0 +1,67 @@+# This file was automatically generated by 'stack init'+#+# Some commonly used options have been documented as comments in this file.+# For advanced use and comprehensive documentation of the format, please see:+# http://docs.haskellstack.org/en/stable/yaml_configuration/++# Resolver to choose a 'specific' stackage snapshot or a compiler version.+# A snapshot resolver dictates the compiler version and the set of packages+# to be used for project dependencies. For example:+#+# resolver: lts-3.5+# resolver: nightly-2015-09-21+# resolver: ghc-7.10.2+# resolver: ghcjs-0.1.0_ghc-7.10.2+# resolver:+# name: custom-snapshot+# location: "./custom-snapshot.yaml"+resolver: nightly-2016-07-30++# User packages to be built.+# Various formats can be used as shown in the example below.+#+# packages:+# - some-directory+# - https://example.com/foo/bar/baz-0.0.2.tar.gz+# - location:+# git: https://github.com/commercialhaskell/stack.git+# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a+# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a+# extra-dep: true+# subdirs:+# - auto-update+# - wai+#+# A package marked 'extra-dep: true' will only be built if demanded by a+# non-dependency (i.e. a user package), and its expr suites and benchmarks+# will not be run. This is useful for tweaking upstream packages.+packages:+- '.'+# Dependency packages to be pulled from upstream that are not in the resolver+# (e.g., acme-missiles-0.3)+extra-deps:+ - show-type-0.1.1++# Override default flag values for local packages and extra-deps+flags: {}++# Extra package databases containing global packages+extra-package-dbs: []++# Control whether we use the GHC we find on the path+# system-ghc: true+#+# Require a specific version of stack, using version ranges+# require-stack-version: -any # Default+# require-stack-version: ">=1.1"+#+# Override the architecture used by stack, especially useful on Windows+# arch: i386+# arch: x86_64+#+# Extra directories used by stack for building+# extra-include-dirs: [/path/to/dir]+# extra-lib-dirs: [/path/to/dir]+#+# Allow a newer minor version of GHC than the snapshot specifies+# compiler-check: newer-minor
type-spec.cabal view
@@ -1,5 +1,5 @@ name: type-spec-version: 0.1.0.0+version: 0.2.0.0 synopsis: Type Level Specification by Example description: Please see README.md homepage: https://github.com/sheyll/type-spec#readme@@ -8,10 +8,13 @@ author: Sven Heyll maintainer: sven.heyll@gmail.com copyright: 2016 Sven Heyll-category: expring+category: Testing build-type: Simple--- extra-source-files:-cabal-version: >=1.10+extra-source-files: examples/Main.hs+ , README.md+ , stack.yaml+ , .travis.yml+cabal-version: >=1.10 library hs-source-dirs: src