-
Notifications
You must be signed in to change notification settings - Fork 1
/
aos.go
133 lines (112 loc) · 2.97 KB
/
aos.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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
130
131
132
133
package maybe
import (
"errors"
"fmt"
)
// AoS implements the Maybe monad for a slice of strings. An AoS is
// considered 'valid' or 'invalid' depending on whether it contains a slice of
// strings or an error value. A zero-value AoS is invalid and Unbox() will
// return an error to that effect.
type AoS struct {
just []string
err error
}
// NewAoS constructs an AoS from a given slice of strings or error. If e is
// not nil, returns ErrAoS(e), otherwise returns JustAoS(s)
func NewAoS(s []string, e error) AoS {
if e != nil {
return ErrAoS(e)
}
return JustAoS(s)
}
// JustAoS constructs a valid AoS from a given slice of strings.
func JustAoS(s []string) AoS {
return AoS{just: s}
}
// ErrAoS constructs an invalid AoS from a given error.
func ErrAoS(e error) AoS {
return AoS{err: e}
}
// IsErr returns true for an invalid AoS.
func (m AoS) IsErr() bool {
return m.just == nil || m.err != nil
}
// Bind applies a function that takes a slice of strings and returns an AoS.
func (m AoS) Bind(f func(s []string) AoS) AoS {
if m.IsErr() {
return m
}
return f(m.just)
}
// Join applies a function that takes a slice of strings and returns an S.
func (m AoS) Join(f func(s []string) S) S {
if m.IsErr() {
return ErrS(m.err)
}
return f(m.just)
}
// Split applies a splitting function to each element of a valid AoS,
// resulting in a higher-dimension structure. If the AoS is invalid or if any
// function returns an invalid AoS, Split returns an invalid AoAoS.
func (m AoS) Split(f func(s string) AoS) AoAoS {
if m.IsErr() {
return ErrAoAoS(m.err)
}
xss := make([][]string, len(m.just))
for i, v := range m.just {
xs, err := f(v).Unbox()
if err != nil {
return ErrAoAoS(err)
}
xss[i] = xs
}
return JustAoAoS(xss)
}
// Map applies a function to each element of a valid AoS and returns a new
// AoS. If the AoS is invalid or if any function returns an invalid S, Map
// returns an invalid AoS.
func (m AoS) Map(f func(s string) S) AoS {
if m.IsErr() {
return m
}
xss := make([]string, len(m.just))
for i, v := range m.just {
str, err := f(v).Unbox()
if err != nil {
return ErrAoS(err)
}
xss[i] = str
}
return JustAoS(xss)
}
// ToInt applies a function that takes a string and returns an I.If the AoS is
// invalid or if any function returns an invalid I, ToInt returns an invalid
// AoI.
func (m AoS) ToInt(f func(s string) I) AoI {
if m.IsErr() {
return ErrAoI(m.err)
}
xss := make([]int, len(m.just))
for i, v := range m.just {
num, err := f(v).Unbox()
if err != nil {
return ErrAoI(err)
}
xss[i] = num
}
return JustAoI(xss)
}
// String returns a string representation, mostly useful for debugging.
func (m AoS) String() string {
if m.IsErr() {
return fmt.Sprintf("Err %v", m.err)
}
return fmt.Sprintf("Just %v", m.just)
}
// Unbox returns the underlying slice of strings value or error.
func (m AoS) Unbox() ([]string, error) {
if m.just == nil && m.err == nil {
return nil, errors.New("zero-value AoS")
}
return m.just, m.err
}