README
¶
scion-tools
[!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.
Elm inspired functional programing in Go
Table of Content
[!NOTE] For brevity we will use
[]to signify aList[T]and(,)to signify aTuple[A,B].You can use the
FromSliceutility to create aList[T]from a slice.
// example
[1,2,3] => list.FromSlice([]int{1,2,3})
(true,1) => tuple.Pair(true,1)
The Why
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.
The when
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
Basics
import "github.com/Confidenceman02/scion-tools/pkg/basics"
Tons of useful functions.
Int
A wrapped Go int.
type Int int
Float
A wrapped Go float32.
type Float float32
Number
A type alias for Int and Float
type Number interface {
Int | Float
}
Comparable
A special type that represents all types that can be compared:
Add
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) // 31
Sub
func Sub[T Number](a, b T) T
Subtract numbers.
var n1 Int = 4
var n2 Int = 3
Sub(n1, n2) // 1
Fdiv
func 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.25
Mul
func Mul[T Number](a, b T) T
Multiply numbers.
var n1 Int = 2
var n2 Int = 6
Mul(n1, n2) // 6
ToFloat
func 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)
}
Round
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) // -2
Floor
func 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) // -2
Ceiling
func 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) // -1
Truncate
func 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) // -1
Eq
func 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) // true
Lt
func Lt[T Comparable[T]](x T, y T) bool
(<)
var arg1 String = String("123")
var arg2 String = String("456")
Lt(arg1, arg2) // true
Gt
func Gt[T Comparable[T]](x T, y T) bool
(>)
var arg1 String = String("123")
var arg2 String = String("456")
Gt(arg1, arg2) // false
Le
func Le[T Comparable[T]](x T, y T) bool
(<=)
var arg1 String = String("123")
var arg2 String = String("456")
Le(arg1, arg2) // True
Ge
func Ge[T Comparable[T]](x T, y T) bool
(>=)
var arg1 String = String("123")
var arg2 String = String("456")
Ge(arg1, arg2) // False
Max
func Max[T Comparable[T]](x T, y T) T
Find the larger of two comparables.
Max(42,12345678) // 12345678
Max("abc","xyz") // "xyz"
Min
func Min[T Comparable[T]](x T, y T) T
Find the smaller of two comparables.
Min(42,12345678) // 42
Min("abc","xyz") // "abc"
Compare
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) // GT
Order
Represents the relative ordering of two things. The relations are less than, equal to, and greater than.
LT{}
EQ{}
GT{}
Not
func Not(pred bool) bool
Negate a boolean value.
not(true) // false
not(false) // true
Append
func 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"
ModBy
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) // 1
Negate
func Negate[A Number](n A) A
Negate a number.
Negate(42) // -42
Negate(-42) // 42
Negate(0) // 0
Sqrt
func Sqrt(n Float) Float
Take the square root of a number.
Sqrt(4) // 2
Sqrt(9) // 3
Sqrt(16) // 4
Sqrt(25) // 5
Identity
func Identity[A any](x A) A
Given a value, returns exactly the same value. This is called the identity function.
ComposeL
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) // false
Bitwise
import "github.com/Confidenceman02/scion-tools/pkg/bitwise"
Package for bitwise operations.
And
func And(a, b Int) Int
Bitwise AND
ShiftRightBy
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) // -16
ShiftLeftBy
func 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) // 32
Char
import "github.com/Confidenceman02/scion-tools/pkg/char"
Functions for working with runes. Rune literals are enclosed in 'a' pair of single quotes.
IsDigit
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') // False
Dict
import "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.
Empty
func Empty[K Comparable[K], V any]() Dict[K, V]
Create an empty dictionary.
Empty()
Singleton(Dict)
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]
Insert
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"))
Update
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.
Remove
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"))
IsEmpty
func IsEmpty[K Comparable[K], V any](d Dict[K, V]) bool
Determine if a dictionary is empty.
IsEmpty(Empty()) // true
Member(Dict)
func 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")) // true
Get
func 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"
Size
func Size[K Comparable[K], V any](d Dict[K, V]) Int
Determine the number of key-value pairs in the dictionary.
Keys
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]
Values
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"]
ToList
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.
FromList
func FromList[K Comparable[K], V any](l list.List[tuple.Tuple2[K, V]]) Dict[K, V]
Convert an association list into a dictionary.
Map(Dict)
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.
Foldl(Dict)
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.
Foldr(Dict)
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.
Filter
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.
Partition
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.
Union
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.
Intersect
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.
Diff
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.
Merge
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.
List
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!
FromSlice
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]
FromSliceMap
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]
ToSlice
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}
ToSliceMap
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}
Empty
func Empty[T any]() List[T]
Create a list with no elements.
Empty[int]() // []
Singleton(List)
func Singleton[T any](val T) List[T]
Create a list with only one element.
Singleton(1234) // [1234]
Repeat
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]
Range
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) // []
Cons
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]
Map(List)
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]
IndexedMap
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")]
Foldl
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]
Foldr
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]
Filter
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]
FilterMap
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]
Length
func Length[T any](ls List[T]) basics.Int
Determine the length of a list.
Length([1,2,3]) // 3
Reverse(List)
func Reverse[T any](ls List[T]) List[T]
Reverse a list.
Reverse([1,2,3,4]) // [4,3,2,1]
Member(List)
func Member[T any](val T, l List[T]) bool
Figure out whether a list contains a value.
Member(9, [1,2,3,4]) // false
All
func All[T any](isOkay func(T) bool, l List[T]) bool
Determine if all elements satisfy some test.
All(isEven, [2,4]) // true
Any
func Any[T any](isOkay func(T) bool, l List[T]) bool
Determine if any elements satisfy some test.
Any(isEven, [2,3]) // true
Maximum
func 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 4
Minimum
func 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 1
Sum
func Sum[T basics.Number](xs List[T]) T
Get the sum of the list elements.
Sum([1,2,3]) // 6
Product
func Product[T basics.Number](xs List[T]) T
Get the product of the list elements.
Product([2,2,2]) == 8
Append
func Append[T any](xs List[T], ys List[T]) List[T]
Put two lists together.
Append(['a','b'], ['c']) // ['a','b','c']
Concat
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]
Intersperse
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"]
Map2
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.
Map3
func Map3[A, B, C, result any](f func(A, B, C) result, xs List[A], ys List[B], zs List[C]) List[result]
Map4
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]
Map5
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]
Sort
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]
SortBy
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"]
SortWith
func SortWith[A any](f func(a A, b A) basics.Order, xs List[A]) List[A]
Sort values with a custom comparison function.
IsEmpty
func IsEmpty[T any](l List[T]) bool
Determine if a list is empty.
IsEmpty([]) // True
Head
func Head[T any](l List[T]) maybe.Maybe[T]
Extract the first element of a list.
Head([1,2,3]) // Just 1
Tail
func Tail[T any](l List[T]) maybe.Maybe[List[T]]
Extract the rest of the list.
Tail([1,2,3]) // Just [2,3]
Take
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]
Drop
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]
Partition
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])
Unzip
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])
Maybe
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 Nothing
WithDefault
func 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}) // 42
Map(Maybe)
func 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 3
Map2
func 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 7
Map3
func 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]
Map4
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]
Map5
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]
AndThen
func AndThen[A, B any](f func(A) Maybe[B], m Maybe[A]) Maybe[B]
Chain together many computations that may fail.
MaybeWith
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
Set
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.
Empty(Set)
func Empty[K Comparable[K]]() Set[K]
Create an empty set.
Singleton(Set)
func Singleton[K Comparable[K]](v K) Set[K]
Create a set with one value.
Insert(Set)
func Insert[K Comparable[K]](k K, s Set[K]) Set[K]
Insert a value into a set.
Remove(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.
IsEmpty(Set)
func IsEmpty[K Comparable[K]](s Set[K]) bool
Determine if a set is empty.
Member(Set)
func Member[K Comparable[K]](k K, s Set[K]) bool
Determine if a value is in a set.
Size(Set)
func Size[K Comparable[K]](s Set[K]) Int
Determine the number of elements in a set.
Union(Set)
func Union[K Comparable[K]](s1 Set[K], s2 Set[K]) Set[K]
Get the union of two sets. Keep all values.
Intersect(Set)
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.
Diff(Set)
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.
ToList(Set)
func ToList[K Comparable[K]](s Set[K]) list.List[K]
Convert a set into a list, sorted from lowest to highest.
FromList(Set)
func FromList[K Comparable[K]](xs list.List[K]) Set[K]
Convert a list into a set, removing any duplicates.
Map(Set)
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.
Foldl(Set)
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.
Foldr(Set)
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.
Filter(Set)
func Filter[A Comparable[A]](isGood func(A) bool, s Set[A]) Set[A]
Only keep elements that pass the given test.
Partition(Set)
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.
Result
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.
ResultWith
func ResultWith[E, V, R any]( r Result[E, V], err func(Err[E, V]) R, ok func(Ok[E, V]) R) R
Map(Result)
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"
Map2(Result)
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"
Map3(Result)
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]
Map4(Result)
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]
Map5(Result)
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]
AndThen(Result)
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.
WithDefault
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.
ToMaybe
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.
FromMaybe
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.
MapError
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:
String
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 string
IsEmpty(String)
func IsEmpty(x String) bool
Determine if a string is empty.
IsEmpty("") // true
Length(String)
func Length(x String) basics.Int
Get the length of a string.
Length("innumerable") // 11
Reverse(String)
func Reverse(x String) String
Reverse a string.
Reverse("stressed") // "desserts"
Repeat(String)
func Repeat(n basics.Int, chunk String) String
Repeat a string n times.
Repeat(3,"ha") // "hahaha"
Replace
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"
Append
func Append(x String, y String) String
Append two strings. You can also use basics.Append to do this.
Append("butter","fly") // "butterfly"
Concat
func Concat(chunks list.List[String]) String
Concatenate many strings into one.
Concat(["never","the","less"] ) // "nevertheless"
ConcatMap
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.
Split
func Split(sep String, s String) list.List[String]
Split a string using a given separator.
Split(",","cat,dog,cow") // ["cat","dog","cow"]
Join
func Join(sep String, chunks list.List[String]) String
Put many strings together with a given separator.
Join("a",["H","w","ii","n"]) // "Hawaiian"
Words
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?"]
Lines
func Lines(str String) list.List[String]
Break a string into lines, splitting on newlines.
Lines("How are you?\nGood?") // ["How are you?", "Good?"]
Slice
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"
Left
func Left(n basics.Int, str String) String
Take n characters from the left side of a string.
Left(2,"Mulder") // "Mu"
Right
func Right(n basics.Int, str String) String
Take n characters from the right side of a string.
Right(2,"Scully") // "ly"
DropLeft
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"
DropRight
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"
Contains
func Contains(sub String, str String) bool
See if the second string contains the first one.
Contains("the","theory") // true
StartsWith
func StartsWith(sub String, str String) bool
See if the second string starts with the first one.
StartsWith("the","theory") // true
EndsWith
func EndsWith(sub String, str String) bool
See if the second string ends with the first one.
EndsWith("the","theory") // false
Indexes
func 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]
Indices
func Indices(sub String, str String) list.List[basics.Int]
Alias for indexes.
Indexes("i","Mississippi") // [1,4,7,10]
ToInt
func ToInt(x String) maybe.Maybe[basics.Int]
Try to convert a string into an int, failing on improperly formatted strings.
ToInt("123") // Just 123
FromInt
func FromInt(x basics.Int) String
Convert an Int to a String.
FromInt(123) // "123"
ToFloat
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.0
FromFloat
func FromFloat(x basics.Float) String
Convert a Float to a String.
FromFloat(123) // "123"
FromChar
func FromChar(char char.Char) String
Create a string from a given character.
FromFloat(123) // "123"
Cons(String)
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"
Uncons
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")
ToList
func ToList(str String) list.List[char.Char]
Convert a string to a list of characters.
ToList("abc") // ['a','b','c']
FromList
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"
ToUpper
func ToUpper(str String) String
Convert a string to all upper case. Useful for case-insensitive comparisons and VIRTUAL YELLING.
ToUpper("skinner") // "SKINNER"
ToLower
func ToLower(str String) String {
Convert a string to all lower case. Useful for case-insensitive comparisons.
ToLower("X-FILES") // "x-files"
Pad
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 "
PadLeft
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"
PadRight
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...."
Trim
func Trim(str String) String
Get rid of whitespace on both sides of a string.
Trim(" hats \n") // "hats"
TrimLeft
func TrimLeft(str String) String
Get rid of whitespace on the left of a string.
TrimLeft(" hats \n") // "hats \n"
TrimRight
func TrimRight(str String) String
Get rid of whitespace on the right of a string.
TrimRight(" hats \n") // " hats"
Map(String)
func Map(f func(char.Char) char.Char, str String) String
Transform every character in a string
Filter
func Filter(isGood func(char.Char) bool, str String) String
Keep only the characters that pass the test.
Filter(IsDigit,"R2-D2") // "22"
Foldl(String)
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"
Foldr(String)
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"
Any(String)
func Any(isGood func(char.Char) bool, str String) bool
Determine whether any characters pass the test.
Any(IsDigit,"90210") // true
All(String)
func All(isGood func(char.Char) bool, str String) bool
Determine whether all characters pass the test.
All(IsDigit,"90210") == true
Tuple
import "github.com/Confidenceman02/scion-tools/pkg/tuple"
This package is a bunch of helpers for working with 2-tuples.
Pair
func Pair[A, B any](a A, b B) Tuple2[A, B]
Create a 2-tuple.
Pair(3,4) // (3,4)
First
func First[A, B any](t Tuple2[A, B]) A
Extract the first value from a tuple.
First((3,4)) // 3
Second
func Second[A, B any](t Tuple2[A, B]) B
Extract the second value from a tuple.
Second((3, 4)) // 4
MapFirst
func 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)
MapSecond
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)
MapBoth
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)
Directories
¶
| Path | Synopsis |
|---|---|
|
pkg
|
|
|
basics
Package basics has a heap of useful functions inspired by the Elm basics module.
|
Package basics has a heap of useful functions inspired by the Elm basics module. |
|
dict
Package dict implements an immutable dictionary, mapping unique keys to values.
|
Package dict implements an immutable dictionary, mapping unique keys to values. |
|
list
You can create a `List` from any Go slice with the `FromSlice` function.
|
You can create a `List` from any Go slice with the `FromSlice` function. |
|
maybe
Package maybe can help you with optional arguments, error handling, and records with optional fields.
|
Package maybe can help you with optional arguments, error handling, and records with optional fields. |
|
result
A Result is either Ok meaning the computation succeeded, or it is an Err meaning that there was some failure.
|
A Result is either Ok meaning the computation succeeded, or it is an Err meaning that there was some failure. |
|
set
A set of unique values.
|
A set of unique values. |