This is a port of the refined Haskell library to Scala.
The linked websites provides an excellent motivation why this kind of library
is useful.
This library consists of:
-
Type-level predicates for refining other types, like
UpperCase,Positive,Greater[_0] And LessEqual[_2], orLength[Greater[_5]]. There are also higher order predicates for combining proper predicates likeAnd[_, _],Or[_, _],Not[_],Forall[_], orSize[_]. -
A
Predicatetype class that is able to validate a concrete data type (likeDouble) against a type-level predicate (likePositive). -
Two functions
refineandrefineLitthat take a predicatePand some value of typeT, validates this value with aPredicate[P, T]and returns the value with typeT @@ Pif validation was successful or an error otherwise. (@@is shapeless' type for tagging types :-))
scala> refine[Positive, Int](5)
res0: Either[String, Int @@ Positive] = Right(5)
scala> refine[Positive, Int](-5)
re
9C23
s1: Either[String, Int @@ Positive] = Left(Predicate failed: (-5 > 0).)
scala> refineLit[NonEmpty, String]("Hello")
res2: String @@ NonEmpty = Hello
scala> refineLit[NonEmpty, String]("")
<console>:27: error: Predicate isEmpty() did not fail.
refineLit[NonEmpty, String]("")
^
scala> type ZeroToOne = Not[Less[_0]] And Not[Greater[_1]]
defined type alias ZeroToOne
scala> refineLit[ZeroToOne, Double](1.8)
<console>:27: error: Right predicate of (!(1.8 < 0) && !(1.8 > 1)) failed: Predicate (1.8 > 1) did not fail.
refineLit[ZeroToOne, Double](1.8)
^
scala> refineLit[AnyOf[Digit :: Letter :: Whitespace :: HNil], Char]('F')
res3: Char @@ AnyOf[Digit :: Letter :: Whitespace :: HNil] = FNote that refineLit (which only supports literals) is implemented as macro
and checks at compile time if the given literal conforms to the predicate.
The latest version of the library is 0.0.1, which is built against Scala 2.11.
If you're using SBT, add the following to your build file:
libraryDependencies += "eu.timepit" %% "refined" % "0.0.1"
Instructions for Maven and other build tools is available at search.maven.org.
API documentation of the latest release is available at: http://fthomas.github.io/refined/latest/api/
The library comes with these predefined predicates:
True: constant predicate that is alwaystrueFalse: constant predicate that is alwaysfalseNot[P]: negation of the predicatePAnd[A, B]: conjunction of the predicatesAandBOr[A, B]: disjunction of the predicatesAandBAllOf[PS]: conjunction of all predicates inPSAnyOf[PS]: disjunction of all predicates inPS
Digit: checks if aCharis a digitLetter: checks if aCharis a letterLowerCase: checks if aCharis a lower case characterUpperCase: checks if aCharis an upper case characterWhitespace: checks if aCharis white space
Count[PA, PC]: counts the number of elements in aTraversableOncewhich satisfy the predicatePAand passes the result to the predicatePCEmpty: checks if aTraversableOnceis emptyNonEmpty: checks if aTraversableOnceis not emptyForall[P]: checks if the predicatePholds for all elements of aTraversableOnceExists[P]: checks if the predicatePholds for some elements of aTraversableOnceSize[P]: checks if the size of aTraversableOncesatisfies the predicatePMinSize[N]: checks if the size of aTraversableOnceis greater than or equal toNMaxSize[N]: checks if the size of aTraversableOnceis less than or equal toN
Equal[U]: checks if a value is equal toU
Less[N]: checks if a numeric value is less thanNLessEqual[N]: checks if a numeric value is less than or equal toNGreater[N]: checks if a numeric value is greater thanNGreaterEqual[N]: checks if a numeric value is greater than or equal toNPositive: checks if a numeric value is greater than 0Negative: checks if a numeric value is less than 0Interval[L, H]: checks if a numeric value is in the interval [L,H]
MatchesRegex[R]: checks if aStringmatches the regular expressionR
This library is heavily inspired by the refined library for
Haskell. It even stole its name! Another Scala library that provides type-level
validations is bond.
refined is licensed under the MIT license, available at http://opensource.org/licenses/MIT
and also in the LICENSE file.