Note
There are some packages and functions from the Elm core library that are yet to be implemented. You can see a list of these in the issues.
Note
For brevity we will use [] to signify a List[T] and (,) to signify a Tuple[A,B].
You can use the FromSlice utility to create a List[T] from a slice.
// example
[1,2,3] => list.FromSlice([]int{1,2,3})
(true,1) => tuple.Pair(true,1)
Go is an incredibly powerful and performant language that promotes quality and maintainability through its extensive standard library and emphasis on simplicity. Sometimes however, it can be tricky to express certain functional patterns in an immutable and reusable fashion that is both concise and elegant.
Elm is a statically and strongly typed language with an approachable syntax that provides exceptional programming ergonomics. Elm programs are delightful to write and maintain, largely due to the expressiveness one can harness from its functional programming style.
The scion-tools goal is to give Gophers an expressive functional approach by providing pure Go analogues of Elm's core library, including its immutable data structures.
It's just Go that looks a little bit like Elm.
With scion-tools, Gophers have the ability to leverage functional programming techniques that harmonize with Go's idiomatic patterns that we all know and love. It's encouraged you dip in and out of this functional approach when it makes sense to.
The following scenarios provide some good uses cases where you may benefit from using scion-tools or other functional programming packages that are similar:
- Function composition
- Tail-Call Optimization
- Immutability and persistence
- Sorted maps
- Error handling
- Code reusability
import "github.com/Confidenceman02/scion-tools/pkg/basics"Tons of useful functions.
A wrapped Go int.
type Int intA wrapped Go float32.
type Float float32A type alias for Int and Float
type Number interface {
Int | Float
}A special type that represents all types that can be compared:
func Add[T Number](a, b T) T
Add two numbers. The number type variable means this operation can be specialized to any Number type.
var n1 Int = 20
var n2 Int = 11
Add(n1, n2) // 31func Sub[T Number](a, b T) T
Subtract numbers.
var n1 Int = 4
var n2 Int = 3
Sub(n1, n2) // 1func Fdiv(a Float, b Float) Float
Floating-point division:
var n1 Float = 10
var n2 Float = 4
var n3 Float = -1
Fdiv(n1, n2) // 2.5
Fdiv(n3, n2) // -0.25func Mul[T Number](a, b T) T
Multiply numbers.
var n1 Int = 2
var n2 Int = 6
Mul(n1, n2) // 6func ToFloat[T Int](x T) Float
ToFloat - Convert an integer into a float. Useful when mixing Int and Float values.
func halfOf(num Int) Float {
return ToFloat(number / 2)
}func Round(x Float) Int
Round a number to the nearest integer.
Round(1.0) // 1
Round(1.2) // 1
Round(1.5) // 2
Round(1.8) // 2
Round(-1.2) // -1
Round(-1.5) // -1
Round(-1.8) // -2func Floor(x Float) Int
Floor function, rounding down.
Floor(1.0) // 1
Floor(1.2) // 1
Floor(1.5) // 1
Floor(1.8) // 1
Floor(-1.2) // -2
Floor(-1.5) // -2
Floor(-1.8) // -2func Ceiling(x Float) Int
Ceiling function, rounding up.
Ceiling(1.0) // 1
Ceiling(1.2) // 2
Ceiling(1.5) // 2
Ceiling(1.8) // 2
Ceiling(-1.2) // -1
Ceiling(-1.5) // -1
Ceiling(-1.8) // -1func Truncate(x Float) Int
Truncate a number, rounding towards zero
Truncate(1.0) // 1
Truncate(1.2) // 1
Truncate(1.5) // 1
Truncate(1.8) // 1
Truncate(-1.2) // -1
Truncate(-1.5) // -1
Truncate(-1.8) // -1func Eq[T any](x, y T) bool
Check if values are structurally “the same”.
var arg1 List[string] = FromSlice([]string{"a", "b"}))
var arg2 List[string] = FromSlice([]string{"a", "b"}))
Eq(arg1, arg2) // truefunc Lt[T Comparable[T]](x T, y T) bool
(<)
var arg1 String = String("123")
var arg2 String = String("456")
Lt(arg1, arg2) // truefunc Gt[T Comparable[T]](x T, y T) bool
(>)
var arg1 String = String("123")
var arg2 String = String("456")
Gt(arg1, arg2) // falsefunc Le[T Comparable[T]](x T, y T) bool
(<=)
var arg1 String = String("123")
var arg2 String = String("456")
Le(arg1, arg2) // Truefunc Ge[T Comparable[T]](x T, y T) bool
(>=)
var arg1 String = String("123")
var arg2 String = String("456")
Ge(arg1, arg2) // Falsefunc Max[T Comparable[T]](x T, y T) T
Find the larger of two comparables.
Max(42,12345678) // 12345678
Max("abc","xyz") // "xyz"func Min[T Comparable[T]](x T, y T) T
Find the smaller of two comparables.
Min(42,12345678) // 42
Min("abc","xyz") // "abc"func Compare[T Comparable[T]](x T, y T) Order
Compare any two comparable values. Comparable values include String, Char, Int, Float, or a list or tuple containing comparable values. These are also the only values that work as Dict keys or Set members.
Compare (3,4) // LT
Compare(4,4) // EQ
Compare(5,4) // GTRepresents the relative ordering of two things. The relations are less than, equal to, and greater than.
LT{}
EQ{}
GT{}func Not(pred bool) bool
Negate a boolean value.
not(true) // false
not(false) // truefunc Append[T any](a Appendable[T], b Appendable[T]) Appendable[T]
Put two appendable things together. This includes strings and lists.
Append(String("hello"), String("world")) // "helloworld"func ModBy(modulus Int, x Int) Int
Perform arithmetic. A common trick is to use (n mod 2) to detect even and odd numbers:
ModBy(2,0) // 0
ModBy(2,1) // 1
ModBy(2,2) // 0
ModBy(2,3) // 1func Negate[A Number](n A) A
Negate a number.
Negate(42) // -42
Negate(-42) // 42
Negate(0) // 0func Sqrt(n Float) Float
Take the square root of a number.
Sqrt(4) // 2
Sqrt(9) // 3
Sqrt(16) // 4
Sqrt(25) // 5func Identity[A any](x A) A
Given a value, returns exactly the same value. This is called the identity function.
func ComposeL[A any, B any, C any](g func(B) C, f func(A) B) func(A) C
Function composition, passing results along to the left direction.
isEven := func(i Float) bool { return ModBy(2, Int(i)) == 0 }
composed := ComposeL(isEven, Sqrt)
composed(4) // true
composed(3) // falseimport "github.com/Confidenceman02/scion-tools/pkg/bitwise"Package for bitwise operations.
func And(a, b Int) Int
Bitwise AND
func ShiftRightBy(offset Int, a Int) Int
Shift bits to the right by a given offset, filling new bits with whatever is the topmost bit. This can be used to divide numbers by powers of two.
ShiftRightBy(1,32) // 16
ShiftRightBy(2,32) // 8
ShiftRightBy(1,-32) // -16func ShiftLeftBy(offset Int, a Int) Int
Shift bits to the left by a given offset, filling new bits with zeros. This can be used to multiply numbers by powers of two.
ShiftLeftBy(1, 5) // 10
ShiftLeftBy(5, 1) // 32import "github.com/Confidenceman02/scion-tools/pkg/char"Functions for working with runes. Rune literals are enclosed in 'a' pair of single quotes.
func IsDigit(c Char) bool
Detect digits 0123456789
isDigit('0') // True
isDigit('1') // True
isDigit('9') // True
isDigit('a') // False
isDigit('b') // False
isDigit('A') // Falseimport "github.com/Confidenceman02/scion-tools/pkg/dict"A dictionary mapping unique keys to values. The keys can be any Comparable type. This includes Int, Float, Char, String, and tuples or lists of comparable types. Insert, remove, and query operations all take O(log n) time.
func Empty[K Comparable[K], V any]() Dict[K, V]
Create an empty dictionary.
Empty()func Singleton[K Comparable[K], V any](key K, value V) Dict[K, V]
Create a dictionary with one key-value pair.
Singleton("hello", "world") // Dict[String,string]func Insert[K Comparable[K], V any](key K, v V, d Dict[K, V]) Dict[K, V]
Insert a key-value pair into a dictionary. Replaces value when there is a collision.
Insert(2, "two", Singleton(1,"one"))func Update[K Comparable[K], V any](targetKey K, f func(maybe.Maybe[V]) maybe.Maybe[V], d Dict[K, V]) Dict[K, V]
Update the value of a dictionary for a specific key with a given function.
func Remove[K Comparable[K], V any](key K, d Dict[K, V]) Dict[K, V]
Remove a key-value pair from a dictionary. If the key is not found, no changes are made.
Remove(1, Singleton(1,"one"))func IsEmpty[K Comparable[K], V any](d Dict[K, V]) bool
Determine if a dictionary is empty.
IsEmpty(Empty()) // truefunc Member[K Comparable[K], V any](k K, d Dict[K, V]) bool
Determine if a key is in a dictionary.
Member(1, Singleton(1, "one")) // truefunc Get[K Comparable[K], V any](targetKey K, d Dict[K, V]) maybe.Maybe[V]
Get the value associated with a key. If the key is not found, return [Nothing]. This is useful when you are not sure if a key will be in the dictionary.
Get(1, Singleton(1, "one")) // Just "one"func Size[K Comparable[K], V any](d Dict[K, V]) Int
Determine the number of key-value pairs in the dictionary.
func Keys[K Comparable[K], V any](d Dict[K, V]) list.List[K]
Get all of the keys in a dictionary, sorted from lowest to highest.
Keys(fromList([(0,"Alice"),(1,"Bob")])) == [0,1]func Values[K Comparable[K], V any](d Dict[K, V]) list.List[V]
Get all of the values in a dictionary, in the order of their keys.
Values(fromList([(0,"Alice"),(1,"Bob")])) == ["Alice","Bob"]func ToList[K Comparable[K], V any](d Dict[K, V]) list.List[tuple.Tuple2[K, V]]
Convert a dictionary into an association list of key-value pairs, sorted by keys.
func FromList[K Comparable[K], V any](l list.List[tuple.Tuple2[K, V]]) Dict[K, V]
Convert an association list into a dictionary.
func Map[K Comparable[K], V, B any](f func(key K, value V) B, d Dict[K, V]) Dict[K, B]
Apply a function to all values in a dictionary.
func Foldl[K Comparable[K], V, B any](f func(K, V, B) B, acc B, d Dict[K, V]) B
Fold over the key-value pairs in a dictionary from lowest key to highest key.
func Foldr[K Comparable[K], V, B any](f func(K, V, B) B, acc B, d Dict[K, V]) B
Fold over the key-value pairs in a dictionary from highest key to lowest key.
func Filter[K Comparable[K], V any](isGood func(K, V) bool, d Dict[K, V]) Dict[K, V]
Keep only the key-value pairs that pass the given test.
func Partition[K Comparable[K], V any](isGood func(K, V) bool, d Dict[K, V]) tuple.Tuple2[Dict[K, V], Dict[K, V]]
Partition a dictionary according to some test. The first dictionary contains all key-value pairs which passed the test, and the second contains the pairs that did not.
func Union[K Comparable[K], V any](t1 Dict[K, V], t2 Dict[K, V]) Dict[K, V]
Combine two dictionaries. If there is a collision, preference is given to the first dictionary.
func Intersect[K Comparable[K], V any](t1 Dict[K, V], t2 Dict[K, V]) Dict[K, V]
Keep a key-value pair when its key appears in the second dictionary. Preference is given to values in the first dictionary.
func Diff[K Comparable[K], V any](t1 Dict[K, V], t2 Dict[K, V]) Dict[K, V]
Keep a key-value pair when its key does not appear in the second dictionary.
func Merge[K Comparable[K], A, B, R any]( leftStep func(K, A, R) R, bothStep func(K, A, B, R) R, rightStep func(K, B, R) R, leftDict Dict[K, A], rightDict Dict[K, B], initialResult R, ) R
The most general way of combining two dictionaries. You provide three accumulators for when a given key appears:
- Only in the left dictionary.
- In both dictionaries.
- Only in the right dictionary.
You then traverse all the keys from lowest to highest, building up whatever you want.
import "github.com/Confidenceman02/scion-tools/pkg/list"You can create a List from any Go slice with the FromSlice function. This module has a bunch of functions to help you work with them!
func FromSlice[T any](arr []T) List[T]
Create a List from a Go slice.
FromSlice([]int{1,2,3,4}) // [1,2,3,4]func FromSliceMap[A any, B any](f func(A) B, arr []A) List[B]
Create a List from a Go slice applying a function to every element of the slice.
FromSliceMap(func(i int) Int { return Int(i) },[]int{1,2,3,4}) // [1,2,3,4]func ToSlice[T any](xs List[T]) []T
Create a Go slice from a List.
ToSlice([1,2,3,4]) // []int{1,2,3,4}func ToSliceMap[A any, B any](f func(A) B, xs List[A]) []B
Create a Go slice from a List applying a function to every element of the list.
ToSliceMap(func(i Int) int { return i.T() },[1,2,3,4]) // []int{1,2,3,4}func Empty[T any]() List[T]
Create a list with no elements.
Empty[int]() // []func Singleton[T any](val T) List[T]
Create a list with only one element.
Singleton(1234) // [1234]func Repeat[T any](n basics.Int, val T) List[T]
Create a list with n copies of a value.
Repeat(3,1) // [1,1,1]func Range(low basics.Int, hi basics.Int) List[basics.Int]
Create a list of numbers, every element increasing by one. You give the lowest and highest number that should be in the list.
Range(3,6) // [3, 4, 5, 6]
Range(3,3) // [3]
Range(6,3) // []func Cons[T any](val T, l List[T]) List[T]
Add an element to the front of a list.
Cons(1,Singleton(2)) // [1,2]
Cons(1,Empty()) // [1]func Map[A, B any](f func(A) B, xs List[A]) List[B]
Apply a function to every element of a list.
Map(Sqrt, [1,4,9]) // [1,2,3]
Map(Not, [true,false,true]) // [false,true,false]func IndexedMap[A, B any](f func(basics.Int, A) B, xs List[A]) List[B]
Same as map but the function is also applied to the index of each element (starting at zero).
IndexedMap(tuple.Pair, ["Tom","Sue","Bob"]) // [(0,"Tom"),(1,"Sue"),(2,"Bob")]func Foldl[A, B any](f func(A, B) B, acc B, ls List[A]) B
Reduce a list from the left.
Foldl(Cons,Empty[int](), [1,2,3]) // [3,2,1]func Foldr[A, B any](fn func(A, B) B, acc B, ls List[A]) B
Reduce a list from the right.
Foldr(Cons,Empty(),[1,2,3]) == [1,2,3]func Filter[T any](isGood func(T) bool, list List[T]) List[T]
Keep elements that satisfy the test.
Filter(isEven, [1,2,3,4,5,6]) // [2,4,6]func FilterMap[A, B any](f func(A) maybe.Maybe[B], xs List[A]) List[B]
Filter out certain values. For example, maybe you have a bunch of strings from an untrusted source and you want to turn them into numbers:
func numbers() List[Int] {
return FilterMap(ToInt, ["3","hi","12","4th","May"])
}
// numbers == [3, 12]func Length[T any](ls List[T]) basics.Int
Determine the length of a list.
Length([1,2,3]) // 3func Reverse[T any](ls List[T]) List[T]
Reverse a list.
Reverse([1,2,3,4]) // [4,3,2,1]func Member[T any](val T, l List[T]) bool
Figure out whether a list contains a value.
Member(9, [1,2,3,4]) // falsefunc All[T any](isOkay func(T) bool, l List[T]) bool
Determine if all elements satisfy some test.
All(isEven, [2,4]) // truefunc Any[T any](isOkay func(T) bool, l List[T]) bool
Determine if any elements satisfy some test.
Any(isEven, [2,3]) // truefunc Maximum[T basics.Comparable[T]](xs List[T]) maybe.Maybe[T]
Find the maximum element in a non-empty list.
Maximum([1,4,2]) == Just 4func Minimum[T basics.Comparable[T]](xs List[T]) maybe.Maybe[T]
Find the minimum element in a non-empty list.
Minimum([1,4,2]) == Just 1func Sum[T basics.Number](xs List[T]) T
Get the sum of the list elements.
Sum([1,2,3]) // 6func Product[T basics.Number](xs List[T]) T
Get the product of the list elements.
Product([2,2,2]) == 8func Append[T any](xs List[T], ys List[T]) List[T]
Put two lists together.
Append(['a','b'], ['c']) // ['a','b','c']func Concat[T any](lists List[List[T]]) List[T]
Concatenate a bunch of lists into a single list:
Concat([[1,2], [3], [4,5]]) // [1,2,3,4,5]func Intersperse[T any](sep T, xs List[T]) List[T]
Places the given value between all members of the given list.
Intersperse("on",["turtles","turtles","turtles"]) // ["turtles","on","turtles","on","turtles"]func Map2[A, B, result any](f func(A, B) result, xs List[A], ys List[B]) List[result]
Combine two lists, combining them with the given function. If one list is longer, the extra elements are dropped.
func Map3[A, B, C, result any](f func(A, B, C) result, xs List[A], ys List[B], zs List[C]) List[result]
func Map4[A, B, C, D, result any](f func(A, B, C, D) result, xs List[A], ys List[B], zs List[C], ws List[D]) List[result]
func Map5[A, B, C, D, E, result any](f func(A, B, C, D, E) result, vs List[A], ws List[B], xs List[C], ys List[D], zs List[E]) List[result]
func Sort[T any](xs List[basics.Comparable[T]]) List[basics.Comparable[T]]
Sort values from lowest to highest.
Sort([3,1,5]) == [1,3,5]func SortBy[A any](f func(A) basics.Comparable[A], xs List[A]) List[A]
Sort values by a derived property.
SortBy(String.length,["mouse","cat"]) // ["cat","mouse"]func SortWith[A any](f func(a A, b A) basics.Order, xs List[A]) List[A]
Sort values with a custom comparison function.
func IsEmpty[T any](l List[T]) bool
Determine if a list is empty.
IsEmpty([]) // Truefunc Head[T any](l List[T]) maybe.Maybe[T]
Extract the first element of a list.
Head([1,2,3]) // Just 1func Tail[T any](l List[T]) maybe.Maybe[List[T]]
Extract the rest of the list.
Tail([1,2,3]) // Just [2,3]func Take[T any](n basics.Int, list List[T]) List[T]
Take the first n members of a list.
Take(2,[1,2,3,4]) == [1,2]func Drop[T any](n basics.Int, list List[T]) List[T]
Drop the first n members of a list.
Drop(2,[1,2,3,4]) == [3,4]func Partition[A any](pred func(A) bool, list List[A]) Tuple2[List[A], List[A]]
// Partition a list based on some test. The first list contains all values // that satisfy the test, and the second list contains all the value that do not.
Partition(isEven,[0,1,2,3,4,5]) // ([0,2,4], [1,3,5])func Unzip[A, B any](pairs List[Tuple2[A, B]]) Tuple2[List[A], List[B]]
Decompose a list of tuples into a tuple of lists.
Unzip([(0, true),(17,false),(1337,true)]) // ([0,17,1337], [true,false,true])import "github.com/Confidenceman02/scion-tools/pkg/maybe"Represent values that may or may not exist. It can be useful if you have a record field that is only filled in sometimes. Or if a function takes a value sometimes, but does not absolutely need it.
type Just[A any]
type Nothingfunc WithDefault[A any](a A, m Maybe[A]) A
Provide a default value, turning an optional value into a normal value. This comes in handy when paired with functions like Dict.Get which gives back a Maybe.
WithDefault(100,Just[int]{42}) // 42func Map[A, B any](f func(A) B, m Maybe[A]) Maybe[B]
Transform a Maybe value with a given function:
Map(Sqrt,(Just[Int]{9})) // Just 3func Map2[A, B, value any](f func(a A, b B) value, m1 Maybe[A], m2 Maybe[B]) Maybe[value]
Apply a function if all the arguments are Just a value.
Map2(Add,Just[Int]{3}, Just[Int]{4}) // Just 7func Map3[A, B, C, value any](f func(a A, b B, c C) value, m1 Maybe[A], m2 Maybe[B], m3 Maybe[C]) Maybe[value]
func Map4[A, B, C, D, value any](f func(a A, b B, c C, d D) value, m1 Maybe[A], m2 Maybe[B], m3 Maybe[C], m4 Maybe[D]) Maybe[value]
func Map5[A, B, C, D, E, value any](f func(a A, b B, c C, d D, e E) value, m1 Maybe[A], m2 Maybe[B], m3 Maybe[C], m4 Maybe[D], m5 Maybe[E]) Maybe[value]
func AndThen[A, B any](f func(A) Maybe[B], m Maybe[A]) Maybe[B]
Chain together many computations that may fail.
func MaybeWith[V, R any](m Maybe[V],j func(Just[V]) R,n func(Nothing) R) R
Provide functions for a Maybe's Just and Nothing variants
import "github.com/Confidenceman02/scion-tools/pkg/set"A set of unique values. The values can be any comparable type. This includes Int, Float, Char, String, and tuples or lists of comparable types. Insert, remove, and query operations all take O(log n) time.
func Empty[K Comparable[K]]() Set[K]
Create an empty set.
func Singleton[K Comparable[K]](v K) Set[K]
Create a set with one value.
func Insert[K Comparable[K]](k K, s Set[K]) Set[K]
Insert a value into a set.
func Remove[K Comparable[K]](k K, s Set[K]) Set[K]
Remove a value from a set. If the value is not found, no changes are made.
func IsEmpty[K Comparable[K]](s Set[K]) bool
Determine if a set is empty.
func Member[K Comparable[K]](k K, s Set[K]) bool
Determine if a value is in a set.
func Size[K Comparable[K]](s Set[K]) Int
Determine the number of elements in a set.
func Union[K Comparable[K]](s1 Set[K], s2 Set[K]) Set[K]
Get the union of two sets. Keep all values.
func Intersect[K Comparable[K]](s1 Set[K], s2 Set[K]) Set[K]
Get the intersection of two sets. Keeps values that appear in both sets.
func Diff[K Comparable[K]](s1 Set[K], s2 Set[K]) Set[K]
Get the difference between the first set and the second. Keeps values that do not appear in the second set.
func ToList[K Comparable[K]](s Set[K]) list.List[K]
Convert a set into a list, sorted from lowest to highest.
func FromList[K Comparable[K]](xs list.List[K]) Set[K]
Convert a list into a set, removing any duplicates.
func Map[A Comparable[A], B Comparable[B]](f func(A) B, s Set[A]) Set[B]
Map a function onto a set, creating a new set with no duplicates.
func Foldl[A Comparable[A], B any](f func(A, B) B, initialState B, s Set[A]) B
Fold over the values in a set, in order from lowest to highest.
func Foldr[A Comparable[A], B any](f func(A, B) B, initialState B, s Set[A]) B
Fold over the values in a set, in order from highest to lowest.
func Filter[A Comparable[A]](isGood func(A) bool, s Set[A]) Set[A]
Only keep elements that pass the given test.
func Partition[A Comparable[A]](isGood func(A) bool, s Set[A]) tuple.Tuple2[Set[A], Set[A]]
Create two new sets. The first contains all the elements that passed the given test, and the second contains all the elements that did not.
import "github.com/Confidenceman02/scion-tools/pkg/result"A Result is the result of a computation that may fail. This is a great way to manage errors.
func ResultWith[E, V, R any]( r Result[E, V], err func(Err[E, V]) R, ok func(Ok[E, V]) R) R
func Map[X, A, V any](f func(A) V, ra Result[X, A]) Result[X, V]
Apply a function to a result. If the result is Ok, it will be converted. If the result is an Err, the same error value will propagate through.
Map(sqrt, (Ok[String, Float]{Val: 4.0})) // Ok 2.0
Map(sqrt, (Err[String, Float]{Err: "bad input"})) // Err "bad input"func Map2[X, A, B, value any](f func(A, B) value, ra Result[X, A], rb Result[X, B]) Result[X, value]
Apply a function if both results are Ok. If not, the first Err will propagate through.
Map2(max, Ok[String, Int]{42}, Ok[String, Int]{13}) // Ok 42
Map2(max, Err[String, Int]{"x"} Ok[String, Int]{13}) // Err "x"
Map2(max, Ok[String, Int]{42} Err[String, Int]{"y"}) // Err "y"
Map2(max, Err[String, Int]{"x"} Err[String, Int]{"y"} // Err "x"func Map3[X, A, B, C, value any]( f func(A, B, C) value, ra Result[X, A], rb Result[X, B], rc Result[X, C], ) Result[X, value]
func Map4[X, A, B, C, D, value any]( f func(A, B, C, D) value, ra Result[X, A], rb Result[X, B], rc Result[X, C], rd Result[X, D], ) Result[X, value]
func Map5[X, A, B, C, D, E, value any]( f func(A, B, C, D, E) value, ra Result[X, A], rb Result[X, B], rc Result[X, C], rd Result[X, D], re Result[X, E], ) Result[X, value]
func AndThen[X, A, B any](f func(A) Result[X, B], r Result[X, A]) Result[X, B]
Chain together a sequence of computations that may fail.
func WithDefault[E, V any](r Result[E, V], defaultValue V) V
If the result is Ok return the value, but if the result is an Err then return a given default value.
func ToMaybe[E, V any](r Result[E, V]) maybe.Maybe[V]
Convert to a simpler Maybe if the actual error message is not needed or you need to interact with some code that primarily uses maybes.
func FromMaybe[X, V any](e X, m maybe.Maybe[V]) Result[X, V]
Convert from a simple Maybe to interact with some code that primarily uses Results.
func MapError[X, Y, V any](f func(X) Y, r Result[X, V]) Result[Y, V]
Transform an Err value. For example, say the errors we get have too much information:
import "github.com/Confidenceman02/scion-tools/pkg/string"A built-in representation for efficient string manipulation.
The String type is a wrapper for Go's string.
type String stringfunc IsEmpty(x String) bool
Determine if a string is empty.
IsEmpty("") // truefunc Length(x String) basics.Int
Get the length of a string.
Length("innumerable") // 11func Reverse(x String) String
Reverse a string.
Reverse("stressed") // "desserts"func Repeat(n basics.Int, chunk String) String
Repeat a string n times.
Repeat(3,"ha") // "hahaha"func Replace(before String, after String, str String) String
Replace all occurrences of some substring.
Replace(",","/","a,b,c,d,e") == "a/b/c/d/e"func Append(x String, y String) String
Append two strings. You can also use basics.Append to do this.
Append("butter","fly") // "butterfly"func Concat(chunks list.List[String]) String
Concatenate many strings into one.
Concat(["never","the","less"] ) // "nevertheless"func ConcatMap[A, B any](f func(A) List[B], list List[A]) List[B]
Map a given function onto a list and flatten the resulting lists.
func Split(sep String, s String) list.List[String]
Split a string using a given separator.
Split(",","cat,dog,cow") // ["cat","dog","cow"]func Join(sep String, chunks list.List[String]) String
Put many strings together with a given separator.
Join("a",["H","w","ii","n"]) // "Hawaiian"func Words(str String) list.List[String]
Break a string into words, splitting on chunks of whitespace.
Words("How are \t you? \n Good?") // ["How","are","you?","Good?"]func Lines(str String) list.List[String]
Break a string into lines, splitting on newlines.
Lines("How are you?\nGood?") // ["How are you?", "Good?"]func Slice(start basics.Int, end basics.Int, str String) String
Take a substring given a start and end index. Negative indexes are taken starting from the end of the list.
Slice(7,9,"snakes on a plane!") // "on"func Left(n basics.Int, str String) String
Take n characters from the left side of a string.
Left(2,"Mulder") // "Mu"func Right(n basics.Int, str String) String
Take n characters from the right side of a string.
Right(2,"Scully") // "ly"func DropLeft(n basics.Int, str String) String
Drop n characters from the left side of a string.
DropLeft(2,"The Lone Gunmen") // "e Lone Gunmen"func DropRight(n basics.Int, str String) String
Drop n characters from the right side of a string.
DropRight(2,"Cigarette Smoking Man") // "Cigarette Smoking M"func Contains(sub String, str String) bool
See if the second string contains the first one.
Contains("the","theory") // truefunc StartsWith(sub String, str String) bool
See if the second string starts with the first one.
StartsWith("the","theory") // truefunc EndsWith(sub String, str String) bool
See if the second string ends with the first one.
EndsWith("the","theory") // falsefunc Indexes(sub String, str String) list.List[basics.Int]
Get all of the indexes for a substring in another string.
Indexes("i","Mississippi") // [1,4,7,10]func Indices(sub String, str String) list.List[basics.Int]
Alias for indexes.
Indexes("i","Mississippi") // [1,4,7,10]func ToInt(x String) maybe.Maybe[basics.Int]
Try to convert a string into an int, failing on improperly formatted strings.
ToInt("123") // Just 123func FromInt(x basics.Int) String
Convert an Int to a String.
FromInt(123) // "123"func ToFloat(x String) maybe.Maybe[basics.Float]
Try to convert a string into a float, failing on improperly formatted strings.
ToFloat("123") // Just 123.0func FromFloat(x basics.Float) String
Convert a Float to a String.
FromFloat(123) // "123"func FromChar(char char.Char) String
Create a string from a given character.
FromFloat(123) // "123"func Cons(char char.Char, str String) String
Add a character to the beginning of a string.
Cons('T',"he truth is out there") // "The truth is out there"func Uncons(str String) maybe.Maybe[tuple.Tuple2[char.Char, String]]
Split a non-empty string into its head and tail. This lets you pattern match on strings exactly as you would with lists.
Uncons("abc") // Just ('a',"bc")func ToList(str String) list.List[char.Char]
Convert a string to a list of characters.
ToList("abc") // ['a','b','c']func FromList(chars list.List[char.Char]) String
Convert a list of characters into a String. Can be useful if you want to create a string primarily by consing, perhaps for decoding something.
FromList(['a','b','c']) // "abc"func ToUpper(str String) String
Convert a string to all upper case. Useful for case-insensitive comparisons and VIRTUAL YELLING.
ToUpper("skinner") // "SKINNER"func ToLower(str String) String {
Convert a string to all lower case. Useful for case-insensitive comparisons.
ToLower("X-FILES") // "x-files"func Pad(n basics.Int, char char.Char, str String) String
Pad a string on both sides until it has a given length.
Pad(5,' ',"1" ) == " 1 "func PadLeft(n basics.Int, char char.Char, str String) String {
Pad a string on the left until it has a given length.
PadLeft(5,'.',"1") == "....1"func PadRight(n basics.Int, char char.Char, str String) String
Pad a string on the right until it has a given length.
PadRight(5,'.',"1") // "1...."func Trim(str String) String
Get rid of whitespace on both sides of a string.
Trim(" hats \n") // "hats"func TrimLeft(str String) String
Get rid of whitespace on the left of a string.
TrimLeft(" hats \n") // "hats \n"func TrimRight(str String) String
Get rid of whitespace on the right of a string.
TrimRight(" hats \n") // " hats"func Map(f func(char.Char) char.Char, str String) String
Transform every character in a string
func Filter(isGood func(char.Char) bool, str String) String
Keep only the characters that pass the test.
Filter(IsDigit,"R2-D2") // "22"func Foldl[B any](f func(char.Char, B) B, state B, str String) B
Reduce a string from the left.
Foldl(Cons,"","time") // "emit"func Foldr[B any](f func(char.Char, B) B, state B, str String) B
Reduce a string from the right.
Foldr(cons,"","time") // "time"func Any(isGood func(char.Char) bool, str String) bool
Determine whether any characters pass the test.
Any(IsDigit,"90210") // truefunc All(isGood func(char.Char) bool, str String) bool
Determine whether all characters pass the test.
All(IsDigit,"90210") == trueimport "github.com/Confidenceman02/scion-tools/pkg/tuple"This package is a bunch of helpers for working with 2-tuples.
func Pair[A, B any](a A, b B) Tuple2[A, B]
Create a 2-tuple.
Pair(3,4) // (3,4)func First[A, B any](t Tuple2[A, B]) A
Extract the first value from a tuple.
First((3,4)) // 3func Second[A, B any](t Tuple2[A, B]) B
Extract the second value from a tuple.
Second((3, 4)) // 4func MapFirst[A, B, C any](f func(A) B, t Tuple2[A, C]) Tuple2[B, C]
Transform the first value in a tuple.
MapFirst(string.reverse,("stressed", 16)) // ("desserts", 16)func MapSecond[A, B, C any](f func(B) A, t Tuple2[C, B]) Tuple2[C, A]
Transform the second value in a tuple.
MapSecond(Sqrt,("stressed", 16)) // ("stressed", 4)func MapBoth[A, B, C, D any](f func(A) C, g func(B) D, t Tuple2[A, B]) Tuple2[C, D]
Transform both parts of a tuple.
MapBoth(string.reverse,Sqrt,("stressed", 16)) // ("desserts", 4)