Module: NRSER::Types

Defined in:
lib/nrser/types.rb,
lib/nrser/types/in.rb,
lib/nrser/types/is.rb,
lib/nrser/types/any.rb,
lib/nrser/types/nil.rb,
lib/nrser/types/is_a.rb,
lib/nrser/types/type.rb,
lib/nrser/types/array.rb,
lib/nrser/types/attrs.rb,
lib/nrser/types/maybe.rb,
lib/nrser/types/pairs.rb,
lib/nrser/types/paths.rb,
lib/nrser/types/trees.rb,
lib/nrser/types/where.rb,
lib/nrser/types/hashes.rb,
lib/nrser/types/labels.rb,
lib/nrser/types/tuples.rb,
lib/nrser/types/bounded.rb,
lib/nrser/types/numbers.rb,
lib/nrser/types/strings.rb,
lib/nrser/types/symbols.rb,
lib/nrser/types/booleans.rb,
lib/nrser/types/responds.rb,
lib/nrser/refinements/types.rb,
lib/nrser/types/combinators.rb

Overview

base class for Union and Intersection which combine over a set of types.

Defined Under Namespace

Classes: ArrayOfType, ArrayType, Attrs, Bounded, Combinator, HashType, Intersection, Is, IsA, Responds, TupleType, Type, Union, Where

Type Factory Functions collapse

POSIX_PATH_SEGMENT =

class << self (Eigenclass)

path_segment name: 'POSIXPathSegment'
STR =

class << self (Eigenclass)

str( name: 'StringType' ).freeze
EMPTY_STR =
str( name: 'EmptyStringType', length: 0 ).freeze
NON_EMPTY_STR =
non_empty_str( name: 'NonEmptyStr' ).freeze

Constant Summary collapse

ANY =
where(name: 'AnyType', from_s: ->(s) { s }) { true }.freeze
NIL_TYPE =
is(
  nil,
  name: 'NilType',
  # from_s: ->( s ) {
  #   
  # }
).freeze
ARRAY =

Static instance that is satisfied by anything that is an Array.

ArrayType.new.freeze
ARRAY_PAIR =

.array_pair

array_pair( name: 'ArrayPairType' ).freeze
HASH_PAIR =

.hash_pair

hash_pair( name: 'HashPairType' ).freeze
PAIR =

#pair

pair( name: 'PairType' ).freeze
PATHNAME =

A Pathname type that provides a ‘from_s`

is_a \
Pathname,
name: 'PathnameType',
from_s: ->(string) { Pathname.new string },
to_data: :to_s
NON_EMPTY_PATHNAME =

A type satisfied by a Pathname instance that’s not empty (meaning it’s string representation is not empty).

intersection \
PATHNAME,
where { |value| value.to_s.length > 0 },
name: 'NonEmptyPathnameType'
PATH =
union non_empty_str, NON_EMPTY_PATHNAME, name: 'Path'
ARRAY_LIKE =

.array_like

array_like( name: 'ArrayLikeType' ).freeze
HASH_LIKE =

.hash_like

hash_like( name: 'HashLikeType' ).freeze
TREE =

.tree

tree( name: 'TreeType' ).freeze
HASH =
HashType.new.freeze
LABEL =

.label

label( name: 'LabelType' ).freeze
ZERO =

Zero

is(
  0,
  name: 'ZeroType',
  from_s: method( :parse_number )
).freeze
NUM =

Number (Numeric)

IsA.new(
  Numeric,
  name: 'NumType',
  from_s: method( :parse_number )
).freeze
INT =

Integers

IsA.new(
  Integer,
  name: 'IntType',
  from_s: method( :parse_number )
).freeze
POS_INT =

Positive Integer


Integer greater than zero.

intersection(
  INT,
  bounded(min: 1),
  name: 'PosIntType'
).freeze
NEG_INT =

Negative Integer


Integer less than zero.

intersection(
  INT,
  bounded(max: -1),
  name: 'NegIntType'
).freeze
NON_NEG_INT =

Non-Negative Integer


Positive integers and zero… but it seems more efficient to define these as bounded instead of a union.

intersection INT, bounded(min: 0), name: 'NonNegIntType'
NON_POS_INT =

Non-Positive Integer


negative integers and zero.

intersection INT, bounded(max: 0), name: 'NonPosIntType'
SYM =
sym( name: 'SymType' ).freeze
NON_EMPTY_SYM =
non_empty_sym( name: 'NonEmptySym' ).freeze
TRUE =

booleans

is true, name: 'true', from_s: ->(string) {
  if ['true', 't', '1', 'yes', 'y', 'on'].include? string.downcase
    true
  else
    raise TypeError, "can not convert to true: #{ string.inspect }"
  end
}
FALSE =
is false, name: 'false', from_s: ->(string) {
  if ['false', 'f', '0', 'no', 'n', 'off'].include? string.downcase
    false
  else
    raise TypeError, "can not convert to true: #{ string.inspect }"
  end
}
BOOL =
union TRUE, FALSE

Type Factory Functions collapse

Class Method Summary collapse

Class Method Details

.abs_dir_path(name: 'AbsDirPath', **options) ⇒ return_type

Absolute path to a directory (both an abs_path and an dir_path).

Parameters:

  • name: (type) (defaults to: 'AbsDirPath')

    @todo Add name param description.

Returns:

  • (return_type)

    @todo Document return value.



135
136
137
138
139
140
141
# File 'lib/nrser/types/paths.rb', line 135

def abs_dir_path name: 'AbsDirPath', **options
  intersection \
    abs_path,
    dir_path,
    name: name,
    **options
end

.abs_path(name: 'AbsPath', **options) ⇒ Object

An absolute #path.

Parameters:

  • **options

    see NRSER::Types::Type#initialize



102
103
104
105
106
107
108
# File 'lib/nrser/types/paths.rb', line 102

def abs_path name: 'AbsPath', **options
  intersection \
    path,
    where { |path| path.to_pn.absolute? },
    name: name,
    **options
end

.anyObject

anything



9
10
11
# File 'lib/nrser/types/any.rb', line 9

def self.any
  ANY
end

.array(item_type = any, **options) ⇒ NRSER::Types::Type Also known as: list

ArrayType / ArrayOfType factory function.

Parameters:

  • item_type (Type | Object) (defaults to: any)

    Optional type of items.

Returns:



197
198
199
200
201
202
203
204
205
206
207
# File 'lib/nrser/types/array.rb', line 197

def array item_type = any, **options
  if item_type == any
    if options.empty?
      ARRAY
    else
      ArrayType.new **options
    end
  else
    ArrayOfType.new item_type, **options
  end
end

.array_like(**options) ⇒ return_type

TODO:

Document array_like method.

Returns @todo Document return value.

Parameters:

  • arg_name (type)

    @todo Add name param description.

Returns:

  • (return_type)

    @todo Document return value.



37
38
39
40
41
42
43
44
45
46
# File 'lib/nrser/types/trees.rb', line 37

def self.array_like **options
  if options.empty?
    ARRAY_LIKE
  else
    intersection \
      is_a( Enumerable ),
      respond_to( :each_index ),
      **options
  end
end

.array_pair(**options) ⇒ return_type

TODO:

Document array_pair method.

Returns @todo Document return value.

Parameters:

  • arg_name (type)

    @todo Add name param description.

Returns:

  • (return_type)

    @todo Document return value.



39
40
41
42
43
44
45
46
# File 'lib/nrser/types/pairs.rb', line 39

def self.array_pair **options
  return ARRAY_PAIR if options.empty?
  
  key   = options.delete(:key)    || ANY
  value = options.delete(:value)  || ANY
  
  tuple key, value, **options
end

.attrs(attrs, options = {}) ⇒ Object



36
37
38
# File 'lib/nrser/types/attrs.rb', line 36

def attrs attrs, options = {}
  Attrs.new attrs, **options
end

.boolObject

true or false



39
40
41
# File 'lib/nrser/types/booleans.rb', line 39

def self.bool
  BOOL
end

.booleanObject



43
44
45
# File 'lib/nrser/types/booleans.rb', line 43

def self.boolean
  bool
end

.bounded(**options) ⇒ Object

Bounded



49
50
51
# File 'lib/nrser/types/bounded.rb', line 49

def self.bounded **options
  Bounded.new **options
end

.check(value, type) ⇒ Object

raise an error if value doesn’t match type.



64
65
66
# File 'lib/nrser/types.rb', line 64

def self.check value, type
  make(type).check value
end

.dir_path(name: 'DirPath', **options) ⇒ NRSER::Types::Type

A path that is a directory.

Parameters:

Returns:



118
119
120
121
122
123
124
# File 'lib/nrser/types/paths.rb', line 118

def dir_path name: 'DirPath', **options
  intersection \
    path,
    where { |path| File.directory? path },
    name: name,
    **options
end

.empty_strObject



35
36
37
# File 'lib/nrser/types/strings.rb', line 35

def empty_str
  EMPTY_STR
end

.falseObject



32
33
34
# File 'lib/nrser/types/booleans.rb', line 32

def self.false
  FALSE
end

.file_path(name: 'FilePath', **options) ⇒ Object



145
146
147
148
149
150
151
# File 'lib/nrser/types/paths.rb', line 145

def file_path name: 'FilePath', **options
  intersection \
    path,
    where { |path| File.file? path },
    name: name,
    **options
end

.from_repr(repr) ⇒ Object

make a type instance from a object representation that can come from a YAML or JSON declaration.



134
135
136
137
138
139
140
141
142
143
144
# File 'lib/nrser/types.rb', line 134

def self.from_repr repr
  match repr, {
    str => ->(string) {
      NRSER::Types.method(string.downcase).call
    },
    
    Hash => ->(hash) {
      
    },
  }
end

.hash_like(**options) ⇒ return_type

TODO:

Document hash_like method.

Returns @todo Document return value.

Parameters:

  • arg_name (type)

    @todo Add name param description.

Returns:

  • (return_type)

    @todo Document return value.



59
60
61
62
63
64
65
66
67
68
# File 'lib/nrser/types/trees.rb', line 59

def self.hash_like **options
  if options.empty?
    HASH_LIKE
  else
    intersection \
      is_a( Enumerable ),
      respond_to( :each_pair ),
      **options
  end
end

.hash_pair(**options) ⇒ NRSER::Types::Type

Type for a Hash that consists of only a single key and value pair.

Parameters:

  • name: (String)

    Name to give the new type.

  • **options (Hash)

    Other options to pass to

Returns:



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/nrser/types/pairs.rb', line 61

def self.hash_pair **options
  return HASH_PAIR if options.empty?
  
  hash_options = {}
  {key: :keys, value: :values}.each { |from_key, to_key|
    if options.key? from_key
      hash_options[to_key] = options.delete from_key
    end
  }
  
  if hash_options.empty?
    intersection is_a( Hash ), length( 1 ), **options
  else    
    intersection \
      hash_type( **hash_options ),
      length( 1 ),
      **options
  end
  
end

.hash_type(*args) ⇒ NRSER::Types::HASH, NRSER::Types::Type

Type satisfied by Hash instances.

Parameters:

Returns:



46
47
48
49
50
51
52
# File 'lib/nrser/types/hashes.rb', line 46

def self.hash_type *args
  if args.empty?
    HASH
  else
    HashType.new *args
  end
end

.in(group, **options) ⇒ NRSER::Types::Type

Type that tests value for membership in a group object via that object’s ‘#include?` method.

Parameters:

  • group (#include?)

    ‘#include?` will be called on this value to determine type membership.

Returns:



20
21
22
23
24
# File 'lib/nrser/types/in.rb', line 20

def self.in group, **options
  where( name: "In(#{ group })", **options ) { |value|
    group.include? value
  }
end

.intObject



64
65
66
# File 'lib/nrser/types/numbers.rb', line 64

def self.int
  INT
end

.intersection(*types, **options) ⇒ Object

match all of the types



127
128
129
# File 'lib/nrser/types/combinators.rb', line 127

def self.intersection *types, **options
  Intersection.new *types, **options
end

.is(value, **options) ⇒ Object

an exact value (using ===)



29
30
31
# File 'lib/nrser/types/is.rb', line 29

def self.is value, **options
  Is.new value, **options
end

.is_a(klass, **options) ⇒ Object

class membership



63
64
65
# File 'lib/nrser/types/is_a.rb', line 63

def self.is_a klass, **options
  IsA.new klass, **options
end

.label(**options) ⇒ NRSER::Types::Type

A label is a non-empty String or Symbol.

Parameters:

Returns:



39
40
41
42
43
44
45
# File 'lib/nrser/types/labels.rb', line 39

def self.label **options
  if options.empty?
    LABEL
  else
    union non_empty_str, non_empty_sym, **options
  end
end

.length(exact, options = {}) ⇒ NRSER::Types::Attrs .length(bounds, options = {}) ⇒ NRSER::Types::Attrs

Overloads:

  • .length(exact, options = {}) ⇒ NRSER::Types::Attrs

    Get a length attribute type that specifies an ‘exact` value.

    Examples:

    only_type = NRSER::Types.length 1
    
    only_type.test []
    # => false
    
    only_type.test [:x]
    # => true
    
    only_type.test [:x, :y]
    # => false

    Parameters:

    • exact (Integer)

      Exact non-negative integer that the length must be to satisfy the type created.

    • options (Hash) (defaults to: {})

      Options hash passed up to Type constructor.

    Returns:

  • .length(bounds, options = {}) ⇒ NRSER::Types::Attrs

    Get a length attribute type satisfied by values within a ‘:min` and `:max` (inclusive).

    Examples:

    three_to_five = NRSER::Types.length( {min: 3, max: 5}, name: '3-5' )
    three_to_five.test [1, 2]               # => false
    three_to_five.test [1, 2, 3]            # => true
    three_to_five.test [1, 2, 3, 4]         # => true
    three_to_five.test [1, 2, 3, 4, 5]      # => true
    three_to_five.test [1, 2, 3, 4, 5, 6]   # => false

    Parameters:

    • bounds (Hash)
    • options (Hash) (defaults to: {})

      Options hash passed up to Type constructor.

    Options Hash (bounds):

    • :min (Integer)

      An optional minimum value that the ‘#length` should not be less than.

    • :max (Integer)

      An optional maximum value that the ‘#length` should not be more than.

    • :length (Integer)

      An optional value for both the minimum and maximum.

    Returns:

    • (NRSER::Types::Attrs)

      Type satisfied by a ‘#length` attribute between the `:min` and `:max` (inclusive).



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/nrser/types/attrs.rb', line 97

def length *args
  bounds = {}
  options = if args[1].is_a?( Hash ) then args[1] else {} end
  
  case args[0]
  when ::Integer
    # It's just a length
    bounds[:min] = bounds[:max] = non_neg_int.check args[0]
    
  when ::Hash
    # It's keyword args
    kwds = NRSER.symbolize_keys args[0]
    
    # Pull any :min and :max in the keywords
    bounds[:min] = kwds.delete :min
    bounds[:max] = kwds.delete :max
    
    # But override with :length if we got it
    if length = kwds.delete(:length)
      bounds[:min] = length
      bounds[:max] = length
    end
    
    # (Reverse) merge anything else into the options (options hash values
    # take precedence)
    options = kwds.merge options
    
  else        
    raise ArgumentError, <<-END.squish
      arg must be positive integer or option hash, found:
      #{ args[0].inspect } of type #{ args[0].class }
    END
    
  end
  
  bounded_type = bounded bounds
  
  length_type = if !bounded_type.min.nil? && bounded_type.min >= 0
    # We don't need the non-neg check
    bounded_type
  else
    # We do need the non-neg check
    intersection(non_neg_int, bounded_type)
  end
  
  options[:name] ||= "Length<#{ bounded_type.name }>"
  
  attrs({ length: length_type }, options)
end

.make(value) ⇒ NRSER::Types::Type

Make a Type from a value.

If the ‘value` argument is…

  • a Type, it is returned.

  • a Class, a new IsA matching that class is returned.

    This allows things like

    NRSER::Types.check 's', String
    NRSER::Types.match 's', String, ->(s) { ... }
    
  • anything else, a new Is matching that value is returned.

Parameters:

  • value (Object)

Returns:



52
53
54
55
56
57
58
59
60
# File 'lib/nrser/types.rb', line 52

def self.make value
  if value.is_a? NRSER::Types::Type
    value
  elsif value.is_a? ::Class
    IsA.new value
  else
    Is.new value
  end
end

.match(value, *clauses) ⇒ Object

Raises:

  • (TypeError)


74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/nrser/types.rb', line 74

def self.match value, *clauses
  if clauses.empty?
    raise ArgumentError.new NRSER.dedent <<-END
      Must supply either a single {type => expression} hash argument or a
      even amount of arguments representing (type, expression) pairs after
      `value`.
      
      #{ NRSER::Version.doc_url 'NRSER/Types#match-class_method' }
    END
  end
  
  enum = if clauses.length == 1 && clauses.first.respond_to?(:each_pair)
    clauses.first.each_pair
  else
    unless clauses.length % 2 == 0
      raise TypeError.new NRSER.dedent <<-END
        When passing a list of clauses, it must be an even length
        representing (type, expression) pairs.
        
        Found an argument list with length #{ clauses.length }:
        
        #{ clauses }
      END
    end
    
    clauses.each_slice(2)
  end
  
  enum.each { |type, expression|
    if test value, type
      # OK, we matched! Is the corresponding expression callable?
      if expression.respond_to? :call
        # It is; invoke and return result.
        if expression.arity == 0
          return expression.call
        else
          return expression.call value
        end
      else
        # It's not; assume it's a value and return it.
        return expression
      end
    end
  }
  
  raise TypeError, <<-END.dedent
    Could not match value
    
        #{ value.inspect }
    
    to any of types
    
        #{ enum.map {|type, expression| "\n    #{ type.inspect }"}.join '' }
    
  END
end

.maybe(type) ⇒ Object

nil or the argument type



8
9
10
# File 'lib/nrser/types/maybe.rb', line 8

def self.maybe type
  union nil, type, name: "Maybe(#{ type.name })"
end

.neg_intObject



103
104
105
# File 'lib/nrser/types/numbers.rb', line 103

def self.neg_int
  NEG_INT
end

.nilObject

nothing



14
15
16
# File 'lib/nrser/types/nil.rb', line 14

def self.nil
  NIL_TYPE
end

.non_empty_str(**options) ⇒ Object



40
41
42
43
44
# File 'lib/nrser/types/strings.rb', line 40

def non_empty_str **options
  return NON_EMPTY_STR if options.empty?
  
  str( length: {min: 1}, **options )
end

.non_empty_sym(**options) ⇒ Object



28
29
30
31
32
33
34
35
# File 'lib/nrser/types/symbols.rb', line 28

def self.non_empty_sym **options
  return NON_EMPTY_SYM if options.empty?
  
  intersection \
    SYM,
    attrs( {to_s: non_empty_str} ),
    **options
end

.non_neg_intObject



117
118
119
# File 'lib/nrser/types/numbers.rb', line 117

def self.non_neg_int
  NON_NEG_INT
end

.non_pos_intObject



132
133
134
# File 'lib/nrser/types/numbers.rb', line 132

def self.non_pos_int
  NON_POS_INT
end

.numObject



48
49
50
# File 'lib/nrser/types/numbers.rb', line 48

def self.num
  NUM
end

.pair(**options) ⇒ return_type

TODO:

Document pair method.

Returns @todo Document return value.

Parameters:

  • arg_name (type)

    @todo Add name param description.

Returns:

  • (return_type)

    @todo Document return value.



93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/nrser/types/pairs.rb', line 93

def self.pair **options
  if options.empty?
    PAIR
  else
    type_options = NRSER.slice_keys! options, :key, :value
    
    union \
      array_pair( **type_options ),
      hash_pair( **type_options ),
      **options
  end
end

.parse_number(s) ⇒ Integer, Float

Parse a string into a number.

Returns:

  • (Integer)

    If the string represents a whole integer.

  • (Float)

    If the string represents a decimal number.



18
19
20
21
22
# File 'lib/nrser/types/numbers.rb', line 18

def self.parse_number s
  float = Float s
  int = float.to_i
  if float == int then int else float end
end

.path(**options) ⇒ NRSER::Types::Type

A path is a non-empty String or Pathname.

Parameters:

  • **options

    see NRSER::Types::Type#initialize

Returns:



76
77
78
79
80
81
82
# File 'lib/nrser/types/paths.rb', line 76

def path **options
  if options.empty?
    PATH
  else
    union non_empty_str, NON_EMPTY_PATHNAME, **options
  end
end

.path_segment(**options) ⇒ Object Also known as: path_seg



85
86
87
88
89
90
91
92
93
# File 'lib/nrser/types/paths.rb', line 85

def path_segment **options
  if options.empty?
    POSIX_PATH_SEGMENT
  else
    intersection  non_empty_str,
                  where { |string| ! string.include?( '/' ) },
                  name: 'POSIXPathSegment'
  end
end

.pathname(to_data: :to_s, **options) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/nrser/types/paths.rb', line 57

def pathname to_data: :to_s, **options
  if options.empty? && to_data == :to_s
    PATHNAME
  else
    is_a \
      Pathname,
      name: 'PathnameType',
      from_s: ->(string) { Pathname.new string },
      to_data: to_data,
      **options
  end
end

.pos_intObject



86
87
88
# File 'lib/nrser/types/numbers.rb', line 86

def self.pos_int
  POS_INT
end

.respond_to(name, **options) ⇒ return_type

TODO:

Document respond_to Responds.

Returns @todo Document return value.

Parameters:

  • arg_name (type)

    @todo Add name param description.

Returns:

  • (return_type)

    @todo Document return value.



99
100
101
102
103
104
# File 'lib/nrser/types/responds.rb', line 99

def respond_to name, **options
  responds(
    {[:respond_to?, name] => NRSER::Types::TRUE},
    **options
  )
end

.responds(*args) ⇒ return_type

TODO:

Document responds method.

Returns @todo Document return value.

Parameters:

  • arg_name (type)

    @todo Add name param description.

Returns:

  • (return_type)

    @todo Document return value.



86
87
88
# File 'lib/nrser/types/responds.rb', line 86

def responds *args
  Responds.new *args
end

.str(length: nil, **options) ⇒ Object Also known as: string



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/nrser/types/strings.rb', line 16

def str length: nil, **options
  if length.nil? && options.empty?
    # if there are no options can point to the constant for efficiency
    STR
  else
    if length.nil?
      IsA.new String, from_s: ->(s) { s }, **options
    else
      intersection \
        IsA.new( String, from_s: ->(s) { s } ),
        NRSER::Types.length( length ),
        **options
    end
  end
end

.sym(**options) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/nrser/types/symbols.rb', line 10

def self.sym **options
  if options.empty?
    # if there are no options can point to the constant for efficiency
    SYM
  else
    IsA.new(
      Symbol,
      from_s: :to_sym.to_proc,
      **options
    )
  end
end

.test(value, type) ⇒ Object



69
70
71
# File 'lib/nrser/types.rb', line 69

def self.test value, type
  make(type).test value
end

.tree(**options) ⇒ return_type

TODO:

Document tree method.

Returns @todo Document return value.

Parameters:

  • arg_name (type)

    @todo Add name param description.

Returns:

  • (return_type)

    @todo Document return value.



81
82
83
84
85
86
87
88
89
90
# File 'lib/nrser/types/trees.rb', line 81

def self.tree **options
  if options.empty?
    TREE
  else
    union \
      array_like,
      hash_like,
      **options
  end
end

.trueObject



20
21
22
# File 'lib/nrser/types/booleans.rb', line 20

def self.true
  TRUE
end

.tuple(*types, **options) ⇒ return_type

TODO:

Document tuple method.

Returns @todo Document return value.

Parameters:

  • arg_name (type)

    @todo Add name param description.

Returns:

  • (return_type)

    @todo Document return value.



117
118
119
# File 'lib/nrser/types/tuples.rb', line 117

def self.tuple *types, **options
  TupleType.new *types, **options
end

.union(*types, **options) ⇒ Object

match any of the types



110
111
112
# File 'lib/nrser/types/combinators.rb', line 110

def self.union *types, **options
  NRSER::Types::Union.new *types, **options
end

.where(**options, &block) ⇒ Object

create a type based on a predicate



19
20
21
# File 'lib/nrser/types/where.rb', line 19

def self.where **options, &block
  Where.new block, **options
end

.zeroObject



34
35
36
# File 'lib/nrser/types/numbers.rb', line 34

def self.zero
  ZERO
end