Skip to content

Confidenceman02/scion-tools

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

scion-tools

Actions status

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 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)

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.

Back to top

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

Back to top

Basics

import "github.com/Confidenceman02/scion-tools/pkg/basics"

Tons of useful functions.

Int

A wrapped Go int.

type Int int

Back to top

Float

A wrapped Go float32.

type Float float32

Back to top

Number

A type alias for Int and Float

type Number interface {
  Int | Float
}

Back to top

Comparable

A special type that represents all types that can be compared:

Back to top

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

Back to top

Sub

func Sub[T Number](a, b T) T

Subtract numbers.

var n1 Int = 4
var n2 Int = 3

Sub(n1, n2) // 1

Back to top

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

Back to top

Mul

func Mul[T Number](a, b T) T

Multiply numbers.

var n1 Int = 2
var n2 Int = 6

Mul(n1, n2) // 6

Back to top

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)
}

Back to top

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

Back to top

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

Back to top

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

Back to top

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

Back to top

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

Back to top

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

Back to top

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

Back to top

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

Back to top

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"

Back to top

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"

Back to top

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

Back to top

Order

Represents the relative ordering of two things. The relations are less than, equal to, and greater than.

LT{}
EQ{}
GT{}

Back to top

Not

func Not(pred bool) bool

Negate a boolean value.

not(true) // false
not(false) // true

Back to top

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"

Back to top

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

Back to top

Negate

func Negate[A Number](n A) A

Negate a number.

Negate(42) // -42
Negate(-42) // 42
Negate(0) // 0

Back to top

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

Back to top

Identity

func Identity[A any](x A) A

Given a value, returns exactly the same value. This is called the identity function.

Back to top

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

Back to top

Bitwise

import "github.com/Confidenceman02/scion-tools/pkg/bitwise"

Package for bitwise operations.

And

func And(a, b Int) Int

Bitwise AND

Back to top

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

Back to top

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

Back to top

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

Back to top

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()

Back to top

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]

Back to top

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"))

Back to top

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.

Back to top

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"))

Back to top

IsEmpty

func IsEmpty[K Comparable[K], V any](d Dict[K, V]) bool

Determine if a dictionary is empty.

IsEmpty(Empty()) // true

Back to top

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

Back to top

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"

Back to top

Size

func Size[K Comparable[K], V any](d Dict[K, V]) Int

Determine the number of key-value pairs in the dictionary.

Back to top

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]

Back to top

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"]

Back to top

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.

Back to top

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.

Back to top

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.

Back to top

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.

Back to top

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.

Back to top

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.

Back to top

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.

Back to top

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.

Back to top

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.

Back to top

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.

Back to top

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:

  1. Only in the left dictionary.
  2. In both dictionaries.
  3. Only in the right dictionary.

You then traverse all the keys from lowest to highest, building up whatever you want.

Back to top

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]

Back to top

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]

Back to top

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}

Back to top

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}

Back to top

Empty

func Empty[T any]() List[T]

Create a list with no elements.

Empty[int]() // []

Back to top

Singleton(List)

func Singleton[T any](val T) List[T]

Create a list with only one element.

Singleton(1234) // [1234]

Back to top

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]

Back to top

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) // []

Back to top

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]

Back to top

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]

Back to top

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")]

Back to top

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]

Back to top

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]

Back to top

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]

Back to top

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]

Back to top

Length

func Length[T any](ls List[T]) basics.Int

Determine the length of a list.

Length([1,2,3]) // 3

Back to top

Reverse(List)

func Reverse[T any](ls List[T]) List[T]

Reverse a list.

Reverse([1,2,3,4]) // [4,3,2,1]

Back to top

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

Back to top

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

Back to top

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

Back to top

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

Back to top

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

Back to top

Sum

func Sum[T basics.Number](xs List[T]) T

Get the sum of the list elements.

Sum([1,2,3]) // 6

Back to top

Product

func Product[T basics.Number](xs List[T]) T

Get the product of the list elements.

Product([2,2,2]) == 8

Back to top

Append

func Append[T any](xs List[T], ys List[T]) List[T]

Put two lists together.

Append(['a','b'], ['c']) // ['a','b','c']

Back to top

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]

Back to top

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"]

Back to top

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.

Back to top

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]

Back to top

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]

Back to top

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]

Back to top

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]

Back to top

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"]

Back to top

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.

Back to top

IsEmpty

func IsEmpty[T any](l List[T]) bool

Determine if a list is empty.

IsEmpty([]) // True

Back to top

Head

func Head[T any](l List[T]) maybe.Maybe[T]

Extract the first element of a list.

Head([1,2,3]) // Just 1

Back to top

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]

Back to top

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]

Back to top

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]

Back to top

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])

Back to top

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])

Back to top

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

Back to top

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

Back to top

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

Back to top

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]

Back to top

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]

Back to top

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]

Back to top

AndThen

func AndThen[A, B any](f func(A) Maybe[B], m Maybe[A]) Maybe[B]

Chain together many computations that may fail.

Back to top

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

Back to top

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.

Back to top

Singleton(Set)

func Singleton[K Comparable[K]](v K) Set[K]

Create a set with one value.

Back to top

Insert(Set)

func Insert[K Comparable[K]](k K, s Set[K]) Set[K]

Insert a value into a set.

Back to top

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.

Back to top

IsEmpty(Set)

func IsEmpty[K Comparable[K]](s Set[K]) bool

Determine if a set is empty.

Back to top

Member(Set)

func Member[K Comparable[K]](k K, s Set[K]) bool

Determine if a value is in a set.

Back to top

Size(Set)

func Size[K Comparable[K]](s Set[K]) Int

Determine the number of elements in a set.

Back to top

Union(Set)

func Union[K Comparable[K]](s1 Set[K], s2 Set[K]) Set[K]

Get the union of two sets. Keep all values.

Back to top

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.

Back to top

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.

Back to top

ToList(Set)

func ToList[K Comparable[K]](s Set[K]) list.List[K]

Convert a set into a list, sorted from lowest to highest.

Back to top

FromList(Set)

func FromList[K Comparable[K]](xs list.List[K]) Set[K]

Convert a list into a set, removing any duplicates.

Back to top

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.

Back to top

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.

Back to top

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.

Back to top

Filter(Set)

func Filter[A Comparable[A]](isGood func(A) bool, s Set[A]) Set[A]

Only keep elements that pass the given test.

Back to top

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.

Back to top

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"

Back to top

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"

Back to top

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]

Back to top

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]

Back to top

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]

Back to top

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.

Back to top

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.

Back to top

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.

Back to top

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.

Back to top

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:

Back to top

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

Back to top

Length(String)

func Length(x String) basics.Int

Get the length of a string.

Length("innumerable") // 11

Back to top

Reverse(String)

func Reverse(x String) String

Reverse a string.

Reverse("stressed") // "desserts"

Back to top

Repeat(String)

func Repeat(n basics.Int, chunk String) String

Repeat a string n times.

Repeat(3,"ha") // "hahaha"

Back to top

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"

Back to top

Append

func Append(x String, y String) String

Append two strings. You can also use basics.Append to do this.

Append("butter","fly") // "butterfly"

Back to top

Concat

func Concat(chunks list.List[String]) String

Concatenate many strings into one.

Concat(["never","the","less"] ) // "nevertheless"

Back to top

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.

Back to top

Split

func Split(sep String, s String) list.List[String]

Split a string using a given separator.

Split(",","cat,dog,cow") // ["cat","dog","cow"]

Back to top

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"

Back to top

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?"]

Back to top

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?"]

Back to top

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"

Back to top

Left

func Left(n basics.Int, str String) String

Take n characters from the left side of a string.

Left(2,"Mulder") // "Mu"

Back to top

Right

func Right(n basics.Int, str String) String

Take n characters from the right side of a string.

Right(2,"Scully") // "ly"

Back to top

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"

Back to top

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"

Back to top

Contains

func Contains(sub String, str String) bool

See if the second string contains the first one.

Contains("the","theory") // true

Back to top

StartsWith

func StartsWith(sub String, str String) bool

See if the second string starts with the first one.

StartsWith("the","theory") // true

Back to top

EndsWith

func EndsWith(sub String, str String) bool

See if the second string ends with the first one.

EndsWith("the","theory") // false

Back to top

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]

Back to top

Indices

func Indices(sub String, str String) list.List[basics.Int]

Alias for indexes.

Indexes("i","Mississippi") // [1,4,7,10]

Back to top

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

Back to top

FromInt

func FromInt(x basics.Int) String

Convert an Int to a String.

FromInt(123) // "123"

Back to top

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

Back to top

FromFloat

func FromFloat(x basics.Float) String

Convert a Float to a String.

FromFloat(123) // "123"

Back to top

FromChar

func FromChar(char char.Char) String

Create a string from a given character.

FromFloat(123) // "123"

Back to top

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"

Back to top

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")

Back to top

ToList

func ToList(str String) list.List[char.Char]

Convert a string to a list of characters.

ToList("abc") // ['a','b','c']

Back to top

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"

Back to top

ToUpper

func ToUpper(str String) String

Convert a string to all upper case. Useful for case-insensitive comparisons and VIRTUAL YELLING.

ToUpper("skinner") // "SKINNER"

Back to top

ToLower

func ToLower(str String) String {

Convert a string to all lower case. Useful for case-insensitive comparisons.

ToLower("X-FILES") // "x-files"

Back to top

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  "

Back to top

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"

Back to top

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...."

Back to top

Trim

func Trim(str String) String

Get rid of whitespace on both sides of a string.

Trim("  hats  \n") // "hats"

Back to top

TrimLeft

func TrimLeft(str String) String

Get rid of whitespace on the left of a string.

TrimLeft("  hats  \n") // "hats  \n"

Back to top

TrimRight

func TrimRight(str String) String

Get rid of whitespace on the right of a string.

TrimRight("  hats  \n") // "  hats"

Back to top

Map(String)

func Map(f func(char.Char) char.Char, str String) String

Transform every character in a string

Back to top

Filter

func Filter(isGood func(char.Char) bool, str String) String

Keep only the characters that pass the test.

Filter(IsDigit,"R2-D2") // "22"

Back to top

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"

Back to top

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"

Back to top

Any(String)

func Any(isGood func(char.Char) bool, str String) bool

Determine whether any characters pass the test.

Any(IsDigit,"90210") // true

Back to top

All(String)

func All(isGood func(char.Char) bool, str String) bool

Determine whether all characters pass the test.

All(IsDigit,"90210") == true

Back to top

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)

Back to top

First

func First[A, B any](t Tuple2[A, B]) A

Extract the first value from a tuple.

First((3,4)) // 3

Back to top

Second

func Second[A, B any](t Tuple2[A, B]) B

Extract the second value from a tuple.

Second((3, 4)) // 4

Back to top

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)

Back to top

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)

Back to top

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)

Back to top

About

Elm inspired functional programming in Go

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages