[docsite] add monads extension docs
This commit is contained in:
parent
1d4fa6a18b
commit
9a6450a74b
|
@ -15,7 +15,7 @@ Built-in types are grouped under 6 categories:
|
|||
|
||||
### Categories
|
||||
|
||||
Assuming you included `Dry::Types` ([see instructions](/gems/dry-types/1.0/getting-started)) in a module called `Types`:
|
||||
Assuming you included `Dry::Types` ([see instructions](docs::getting-started)) in a module called `Types`:
|
||||
|
||||
* Nominal types:
|
||||
- `Types::Nominal::Any`
|
||||
|
@ -52,7 +52,7 @@ Assuming you included `Dry::Types` ([see instructions](/gems/dry-types/1.0/getti
|
|||
- `Types::Strict::Array`
|
||||
- `Types::Strict::Hash`
|
||||
|
||||
> All types in the `strict` category are [constrained](/gems/dry-types/1.0/constraints) by a type-check that is applied to make sure that the input is an instance of the primitive:
|
||||
> All types in the `strict` category are [constrained](docs::constraints) by a type-check that is applied to make sure that the input is an instance of the primitive:
|
||||
|
||||
``` ruby
|
||||
Types::Strict::Integer[1] # => 1
|
||||
|
@ -113,4 +113,4 @@ Types::Strict::Integer['1'] # => raises Dry::Types::ConstraintError
|
|||
- `Types::Maybe::Coercible::Array`
|
||||
- `Types::Maybe::Coercible::Hash`
|
||||
|
||||
> `Maybe` types are not available by default - they must be loaded using `Dry::Types.load_extensions(:maybe)`. See [Optional Values](/gems/dry-types/1.0/optional-values) for more information.
|
||||
> `Maybe` types are not available by default - they must be loaded using `Dry::Types.load_extensions(:maybe)`. See [Maybe extension](docs::extensions/maybe) for more information.
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
title: Extensions
|
||||
layout: gem-single
|
||||
name: dry-types
|
||||
sections:
|
||||
- maybe
|
||||
- monads
|
||||
---
|
||||
|
||||
`dry-types` can be extended with extension. Those extensions are loaded with `Dry::Types.load_extensions`.
|
||||
|
||||
Available extensions:
|
||||
|
||||
- [Maybe](docs::extensions/maybe)
|
||||
- [Monads](docs::extensions/monads)
|
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
title: Maybe
|
||||
layout: gem-single
|
||||
name: dry-types
|
||||
---
|
||||
|
||||
The [dry-monads gem](/gems/dry-monads/) provides approach to handling optional values by returning a [_Monad_](/gems/dry-monads/) object. This allows you to pass your type to a `Maybe(x)` block that only executes if `x` returns `Some` or `None`.
|
||||
|
||||
> NOTE: Requires the [dry-monads gem](/gems/dry-monads/) to be loaded.
|
||||
1. Load the `:maybe` extension in your application.
|
||||
|
||||
```ruby
|
||||
require 'dry-types'
|
||||
|
||||
Dry::Types.load_extensions(:maybe)
|
||||
module Types
|
||||
include Dry.Types()
|
||||
end
|
||||
```
|
||||
|
||||
2. Append `.maybe` to a _Type_ to return a _Monad_ object
|
||||
|
||||
```ruby
|
||||
x = Types::Maybe::Strict::Integer[nil]
|
||||
Maybe(x) { puts(x) }
|
||||
x = Types::Maybe::Coercible::String[nil]
|
||||
Maybe(x) { puts(x) }
|
||||
x = Types::Maybe::Strict::Integer[123]
|
||||
Maybe(x) { puts(x) }
|
||||
x = Types::Maybe::Strict::String[123]
|
||||
Maybe(x) { puts(x) }
|
||||
```
|
||||
|
||||
```ruby
|
||||
Types::Maybe::Strict::Integer[nil] # None
|
||||
Types::Maybe::Strict::Integer[123] # Some(123)
|
||||
Types::Maybe::Coercible::Float[nil] # None
|
||||
Types::Maybe::Coercible::Float['12.3'] # Some(12.3)
|
||||
# 'Maybe' types can also accessed by calling '.maybe' on a regular type:
|
||||
Types::Strict::Integer.maybe # equivalent to Types::Maybe::Strict::Integer
|
||||
```
|
||||
|
||||
You can define your own optional types:
|
||||
|
||||
``` ruby
|
||||
maybe_string = Types::Strict::String.maybe
|
||||
maybe_string[nil]
|
||||
# => None
|
||||
maybe_string[nil].fmap(&:upcase)
|
||||
# => None
|
||||
maybe_string['something']
|
||||
# => Some('something')
|
||||
maybe_string['something'].fmap(&:upcase)
|
||||
# => Some('SOMETHING')
|
||||
maybe_string['something'].fmap(&:upcase).value_or('NOTHING')
|
||||
# => "SOMETHING"
|
||||
```
|
|
@ -0,0 +1,61 @@
|
|||
---
|
||||
title: Monads
|
||||
layout: gem-single
|
||||
name: dry-types
|
||||
---
|
||||
|
||||
The monads extension makes `Dry::Types::Result` objects compatible with `dry-monads`.
|
||||
|
||||
To enable the extension:
|
||||
|
||||
```ruby
|
||||
require 'dry/types'
|
||||
Dry::Types.load_extensions(:monads)
|
||||
```
|
||||
|
||||
After loading the extension, you can leverage monad API:
|
||||
|
||||
```ruby
|
||||
Types = Dry.Types()
|
||||
|
||||
result = Types::String.try('Jane')
|
||||
result.class #=> Dry::Types::Result::Success
|
||||
monad = result.to_monad
|
||||
monad.class #=> Dry::Monads::Result::Success
|
||||
monad.value! # => 'Jane'
|
||||
result = Types::String.try(nil)
|
||||
result.class #=> Dry::Types::Result::Failure
|
||||
monad = result.to_monad
|
||||
monad.class #=> Dry::Monads::Result::Failure
|
||||
monad.failure # => [#<Dry::Types::ConstraintError>, nil]
|
||||
Types::String.try(nil)
|
||||
.to_monad
|
||||
.fmap { |result| puts "passed: #{result.inspect}" }
|
||||
.or { |error, input| puts "input '#{input.inspect}' failed with error: #{error.to_s}" }
|
||||
```
|
||||
|
||||
This can be useful when used with `dry-monads` and the [`do` notation](/gems/dry-monads/1.0/do-notation/):
|
||||
|
||||
```ruby
|
||||
require 'dry/types'
|
||||
Types = Dry.Types()
|
||||
Dry::Types.load_extensions(:monads)
|
||||
|
||||
class AddTen
|
||||
include Dry::Monads[:result, :do]
|
||||
|
||||
def call(input)
|
||||
integer = yield Types::Coercible::Integer.try(input)
|
||||
|
||||
Success(integer + 10)
|
||||
end
|
||||
end
|
||||
|
||||
add_ten = AddTen.new
|
||||
|
||||
add_ten.call(10)
|
||||
# => Success(20)
|
||||
|
||||
add_ten.call('integer')
|
||||
# => Failure([#<Dry::Types::CoercionError: invalid value for Integer(): "integer">, "integer"])
|
||||
```
|
|
@ -31,7 +31,7 @@ name: dry-types
|
|||
end
|
||||
```
|
||||
|
||||
2. Define [Custom Types](/gems/dry-types/1.0/custom-types) in the `Types` module, then pass the name & type to `attribute`:
|
||||
2. Define [Custom Types](docs::custom-types) in the `Types` module, then pass the name & type to `attribute`:
|
||||
|
||||
```ruby
|
||||
module Types
|
||||
|
|
|
@ -15,6 +15,7 @@ sections:
|
|||
- enum
|
||||
- map
|
||||
- custom-types
|
||||
- extensions
|
||||
---
|
||||
|
||||
`dry-types` is a simple and extendable type system for Ruby; useful for value coercions, applying constraints, defining complex structs or value objects and more. It was created as a successor to [Virtus](https://github.com/solnic/virtus).
|
||||
|
@ -35,7 +36,7 @@ User.new(name: 'Bob', age: 35)
|
|||
# => #<User name="Bob" age=35>
|
||||
```
|
||||
|
||||
See [Built-in Types](/gems/dry-types/1.0/built-in-types/) for a full list of available types.
|
||||
See [Built-in Types](docs::built-in-types/) for a full list of available types.
|
||||
|
||||
By themselves, the basic type definitions like `Types::String` and `Types::Integer` don't do anything except provide documentation about which type an attribute is expected to have. However, there are many more advanced possibilities:
|
||||
|
||||
|
@ -66,7 +67,7 @@ User.new(name: 'Bob', age: 'not coercible')
|
|||
# => ArgumentError: invalid value for Integer(): "not coercible"
|
||||
```
|
||||
|
||||
- Use `.optional` to denote that an attribute can be `nil` (see [Optional Values](/gems/dry-types/1.0/optional-values)):
|
||||
- Use `.optional` to denote that an attribute can be `nil` (see [Optional Values](docs::optional-values)):
|
||||
|
||||
```ruby
|
||||
class User < Dry::Struct
|
||||
|
@ -84,7 +85,7 @@ User.new(name: 'Bob')
|
|||
# => Dry::Struct::Error: [User.new] :age is missing in Hash input
|
||||
```
|
||||
|
||||
- Add custom constraints (see [Constraints](/gems/dry-types/1.0/constraints.html)):
|
||||
- Add custom constraints (see [Constraints](docs::constraints.html)):
|
||||
|
||||
```ruby
|
||||
class User < Dry::Struct
|
||||
|
@ -120,16 +121,16 @@ Types::Strict::String[10000]
|
|||
|
||||
### Features
|
||||
|
||||
* Support for [constrained types](/gems/dry-types/1.0/constraints)
|
||||
* Support for [optional values](/gems/dry-types/1.0/optional-values)
|
||||
* Support for [default values](/gems/dry-types/1.0/default-values)
|
||||
* Support for [sum types](/gems/dry-types/1.0/sum)
|
||||
* Support for [enums](/gems/dry-types/1.0/enum)
|
||||
* Support for [hash type with type schemas](/gems/dry-types/1.0/hash-schemas)
|
||||
* Support for [array type with members](/gems/dry-types/1.0/array-with-member)
|
||||
* Support for [constrained types](docs::constraints)
|
||||
* Support for [optional values](docs::optional-values)
|
||||
* Support for [default values](docs::default-values)
|
||||
* Support for [sum types](docs::sum)
|
||||
* Support for [enums](docs::enum)
|
||||
* Support for [hash type with type schemas](docs::hash-schemas)
|
||||
* Support for [array type with members](docs::array-with-member)
|
||||
* Support for arbitrary meta information
|
||||
* Support for typed struct objects via [dry-struct](/gems/dry-struct)
|
||||
* Types are [categorized](/gems/dry-types/1.0/built-in-types), which is especially important for optimized and dedicated coercion logic
|
||||
* Types are [categorized](docs::built-in-types), which is especially important for optimized and dedicated coercion logic
|
||||
* Types are composable and reusable objects
|
||||
* No const-missing magic and complicated const lookups
|
||||
* Roughly 6-10 x faster than Virtus
|
||||
|
|
|
@ -32,65 +32,4 @@ optional_string[123]
|
|||
|
||||
### Handle optional values using Monads
|
||||
|
||||
The [dry-monads gem](/gems/dry-monads/) provides another approach to handling optional values by returning a [_Monad_](/gems/dry-monads/) object. This allows you to pass your type to a `Maybe(x)` block that only executes if `x` returns `Some` or `None`.
|
||||
|
||||
> NOTE: Requires the [dry-monads gem](/gems/dry-monads/) to be loaded.
|
||||
|
||||
1. Load the `:maybe` extension in your application.
|
||||
|
||||
```ruby
|
||||
require 'dry-types'
|
||||
|
||||
Dry::Types.load_extensions(:maybe)
|
||||
module Types
|
||||
include Dry.Types()
|
||||
end
|
||||
```
|
||||
|
||||
2. Append `.maybe` to a _Type_ to return a _Monad_ object
|
||||
|
||||
```ruby
|
||||
x = Types::Maybe::Strict::Integer[nil]
|
||||
Maybe(x) { puts(x) }
|
||||
|
||||
x = Types::Maybe::Coercible::String[nil]
|
||||
Maybe(x) { puts(x) }
|
||||
|
||||
x = Types::Maybe::Strict::Integer[123]
|
||||
Maybe(x) { puts(x) }
|
||||
|
||||
x = Types::Maybe::Strict::String[123]
|
||||
Maybe(x) { puts(x) }
|
||||
```
|
||||
|
||||
```ruby
|
||||
Types::Maybe::Strict::Integer[nil] # None
|
||||
Types::Maybe::Strict::Integer[123] # Some(123)
|
||||
|
||||
Types::Maybe::Coercible::Float[nil] # None
|
||||
Types::Maybe::Coercible::Float['12.3'] # Some(12.3)
|
||||
|
||||
# 'Maybe' types can also accessed by calling '.maybe' on a regular type:
|
||||
Types::Strict::Integer.maybe # equivalent to Types::Maybe::Strict::Integer
|
||||
```
|
||||
|
||||
You can define your own optional types:
|
||||
|
||||
``` ruby
|
||||
maybe_string = Types::Strict::String.maybe
|
||||
|
||||
maybe_string[nil]
|
||||
# => None
|
||||
|
||||
maybe_string[nil].fmap(&:upcase)
|
||||
# => None
|
||||
|
||||
maybe_string['something']
|
||||
# => Some('something')
|
||||
|
||||
maybe_string['something'].fmap(&:upcase)
|
||||
# => Some('SOMETHING')
|
||||
|
||||
maybe_string['something'].fmap(&:upcase).value_or('NOTHING')
|
||||
# => "SOMETHING"
|
||||
```
|
||||
See [Maybe](docs::extensions/maybe) extension for another approach to handling optional values by returning a [_Monad_](/gems/dry-monads/) object.
|
||||
|
|
Loading…
Reference in New Issue