Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/Ben-G/Validated
A Swift μ-Library for Somewhat Dependent Types
https://github.com/Ben-G/Validated
Last synced: 3 months ago
JSON representation
A Swift μ-Library for Somewhat Dependent Types
- Host: GitHub
- URL: https://github.com/Ben-G/Validated
- Owner: Ben-G
- License: mit
- Created: 2016-02-25T04:05:36.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2017-04-17T06:48:07.000Z (over 7 years ago)
- Last Synced: 2024-04-24T18:58:28.300Z (6 months ago)
- Language: Swift
- Homepage: http://blog.benjamin-encz.de/validated-a-swift-m-library-for-somewhat-dependent-types/
- Size: 43 KB
- Stars: 607
- Watchers: 15
- Forks: 21
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: Changelog.md
- License: LICENSE.md
Awesome Lists containing this project
- awesome-ios - Validated - A Swift μ-Library for Somewhat Dependent Types. (Utility / Web View)
- awesome-ios-star - Validated - A Swift μ-Library for Somewhat Dependent Types. (Utility / Web View)
README
[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Validated.svg?style=flat-square)](https://cocoapods.org/pods/Validated) [![Platform support](https://img.shields.io/badge/platform-ios%20%7C%20osx%20%7C%20tvos%20%7C%20watchos-lightgrey.svg?style=flat-square)](https://github.com/Ben-G/Validated/blob/master/LICENSE.md)[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![License MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://github.com/Ben-G/Validated/blob/master/LICENSE.md)
# Validated
Validated is a μ-library (~50 Source Lines of Code) that allows you make better use of Swift's type system by providing tools for easily generating new types with built-in guarantees.
Validated allows you to use the type system to verify properties of your values, providing a new level of compile time guarantees.
Using validators you can define new types that add guarantees to existing types:
```swift
// Create a new string type that can never be empty
typealias NonEmptyString = Validated
```## Example
You might have a function in your code that only knows how to work with a `User` value when the user is logged in. Usually you will implement this requirement in code & add documentation, but you don't have an easy way of expressing this invariant in the type signature:
```swift
/// Please ever only call with a logged-in user!
func performTaskWithUser(user: User) {
precondition(
user.loggedIn,
"It is illegal to call this method with a logged out user!"
)// ...
}
```Using Validated you can quickly create a new type that describes this requirement in the type system. That makes it impossible to call the function with a logged-out user and it makes the method signature express your invariant (instead of relying on documentation):
```swift
func performTaskWithUser(user: LoggedInUser) {
// ...
}
```**So how is this new `LoggedInUser` type created?**
First, you need to implement a validator:
```swift
struct LoggedInValidator: Validator {static func validate(value: User) -> Bool {
return value.loggedIn
}}
```
A `Validator` needs to implement the `validate` function that takes the type that this validator can validate (in this case a `User`). The funtion returns a `Bool`. Return `true` if the requirements are fulfilled and `false` if not.With the `Validator` in place we can create our new type like this:
```swift
typealias LoggedInUser = Validated
```Note, that it is not required to provide a typealias, but for most cases it is recommended.
**And that's it!**
`LoggedInUser` now has a failable initializer that takes a `User`. If the passed in `User` fulfills the logged-in requirement you will have a `LoggedInUser`, otherwise `nil`. Additionally `LoggedInUser` provides a throwing initializer, in case you prefer to handle failed validations as errors instead of `nil` values.
The underlying value (the full `User` value) is stored in the `.value` property of `LoggedInUser`.
## Beyond the Basics
Validated provides some further features that might be non-obvious.
### Composing Validators with Logical Operators
Validated offers `Validator` types for logical operations that allow you to require multiple validations in different combinations. E.g. you can use the `And` validator to require that two requirements must be met for your type to intializer:
```swift
typealias AllCapsNonEmptyString =
Validated>
```
`Or` and `Not` are provided as additional validators. You can take a look at the specs for additional examples.### Generic Validators
A `Validator` can itself be generic. This is useful if you want to provide verifications for a whole category of types. The example validator `NonEmptyCollectionValidator` can be applied to all validator types by using a generic requirement:
```swift
struct NonEmptyCollectionValidator: Validator {
static func validate(value: T) -> Bool {
if !value.isEmpty {
return true
} else {
return false
}
}
}
```
However, when using this validator to create a type, you will have to specify the exact type of collection you want to validate:```swift
typealias NonEmptyListOfStrings = Validated<[String], NonEmptyCollectionValidator<[String]>>
```# Does this Library Enable Dependent Types?
No, not really. Dependent types would allow us to define types, solely based on values. This library only allows us to validate if a type is of a specified type `` based on its value and a validator. The value itself doesn't change the type information.
Truely dependent types would create the following results:
```swift
[1, 2, 3] // type = Array
[1, 2, 3, 4] // type = Array
```Using Validated we can only verify if a type falls into one of our statically defined categories:
```swift
ListOf3([1,2,3]) // type = ListOf3
ListOf3([1,2,3,4]) // type = nil
```However, these statically provided checks can still add a lot of value to your code; see the examples above.
# Installation
Validated is available via the usual suspects.
## CocoaPods
You can install Validated via CocoaPods by adding it to your `Podfile`:
use_frameworks!
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
pod 'Validated'And run `pod install`.
## Carthage
You can install Validated via Carthage by adding the following line to your Cartfile:
github "Ben-G/Validated"
# Get in touch
If you have any questions, you can find me on twitter [@benjaminencz](https://twitter.com/benjaminencz).