Make Go functional with dogs

dogs

ci status Go Reference

logo

Make Go functional with dogs

Caution

This is a highly-experimental package. Any changes will be made in a backward-incompatible manner.

This package will not compile without gotip since type parameters are not supported currently in any of Go releases.

Probably you don't need this even after type parameters becomes GA. Even if you feel you do, maybe you shouldn't use this. It's against Go's philosophy.

Features

We will continue to implement more utility types and functions.

Type classes

  • Eq
  • Ord
  • Semigroup
  • Monoid

Data types

  • Pair
  • List
  • Slice
  • Map
  • Set
  • Iterator

Examples

More examples here.

FizzBuzz

func main() {
	monoid := option.DeriveMonoid[string](algebra.DeriveAdditiveSemigroup[string]())
	fizzBuzz := func(i int) string {
		fizz := option.Filter(option.Some[string]("Fizz"), func(_ string) bool { return i%3 == 0 })
		buzz := option.Filter(option.Some[string]("Buzz"), func(_ string) bool { return i%5 == 0 })
		return option.UnwrapOr(monoid.Combine(fizz, buzz), fmt.Sprint(i))
	}
	it := iterator.Map(iterator.Range[int](1, 15), fizzBuzz)
	iterator.ForEach(it, func(s string) { fmt.Println(s) })
}

Fibonacci

func main() {
	type Pair = pair.Pair[int, int]
	it := iterator.Unfold(
		Pair{1, 1},
		func(p Pair) (Pair, int, bool) {
			a, b := p.Values()
			return Pair{b, a + b}, a, true
		},
	)
	iterator.ForEach(
		iterator.Take(it, 5),
		func(i int) { fmt.Println(i) },
	)
}

Acknowledgements

This library is inspired mainly by:

and many other functional languages.

License

Distributed under the Apache License, Version 2.0. See LICENSE for more information.

Owner
Genta Kamitani
Kyoto -> Tokyo
Genta Kamitani
Comments
  • Examples needed.

    Examples needed.

    Hello @genkami!

    First of all thank you for this nice project. I've recently discovered it and find it interesting.

    I wanted to send you a letter, but then thought, that this issue maybe useful to some other enthusiasts, and also I can use the markdown formatting. Apologies for a long read and for the fact that I haven't had the chance to push the project to GitHub yet.

    Before the generics were available I was playing around Monoids in Golang. My favourite example is FizzBuzz!

    So I implemented the solution which was highly inspired by a couple of articles mentioned bellow. The first approach looked something like this:

    // FizzBuzzFunctional
    //
    // https://web.archive.org/web/20130511210903/http://dave.fayr.am/posts/2012-10-4-finding-fizzbuzz.html
    // https://medium.com/@iopguy/fizzbuzz-can-finally-be-implemented-in-stable-rust-87649a882f2d
    // https://www.parsonsmatt.org/2016/02/27/an_elegant_fizzbuzz.html
    func FizzBuzzFunctional(n int) string {
    	m := monoid.ForString("").
    		Append(monoid.ForString("Fizz").Filtered(func() bool {
    			return n%3 == 0
    		})).
    		Append(monoid.ForString("Buzz").Filtered(func() bool {
    			return n%5 == 0
    		}))
    
    	return m.UnwrapOr(strconv.Itoa(n))
    }
    

    I had to implement an Optional type (an equivalent of Maybe, the name seemed more conventional for Golang). UnwrapOr is basically FromMaybe in Haskell. After that I turned that Optional into a monoid. The API is not ideal, but the solution looks pretty simple. Given that we don't have the monadic list comprehensions I used Filtered function to add the predicated. So basically the structure that implemented the monoid, also had a Filtered method. Not very elegant, but better than nothing.

    The beauty of this solution is that we can easily add more predicates: Fizz, Buzz, Bizz, etc... However in order for it to work we need to be able to create a Monoid which is basically a function, and not a concrete a simple type.

    My Optional Monoidlooked like this:

    package monoid
    
    type OptionString struct {
    	op option.String
    }
    
    // SomeString wraps the s into an optional string.
    func SomeString(s string) OptionString {
    	return OptionString{
    		op: option.SomeString(s),
    	}
    }
    
    // NoneString returns an empty optional string.
    func NoneString() OptionString {
    	return OptionString{
    		op: option.NoneString(),
    	}
    }
    
    func (m OptionString) Empty() OptionString {
    	return NoneString()
    }
    
    func (m OptionString) Append(other OptionString) OptionString {
    	switch {
    	case m == NoneString():
    		return other
    	case other == NoneString():
    		return m
    	default:
    		return SomeString(m.op.Append(other.op).UnwrapOrDefault())
    	}
    }
    
    func (m OptionString) Filtered(fn func() bool) OptionString {
    	if fn() {
    		return m
    	}
    
    	return NoneString()
    }
    
    func (m OptionString) UnwrapOr(s string) string {
    	return m.op.UnwrapOr(s)
    }
    

    It was using a String Option which supported the Append for convenience, however it was not a Monoid, it didn't respect the Monodic laws, however the monoid.OptionsSting did:

    func TestOptionString(t *testing.T) {
    	t.Parallel()
    
    	// A set S equipped with a binary operation S × S → S,
    	// which we will denote •, is a monoid if it satisfies the following two axioms:
    
    	t.Run("it has valid identity", func(t *testing.T) {
    		t.Parallel()
    
    		m := monoid.SomeString("test")
    
    		// There exists an element e in S such that for every element a in S,
    		// the equations e • a = a and a • e = a hold.
    		AssertEqual(t, m, m.Append(m.Empty()))
    		AssertEqual(t, m.Empty().Append(m), m.Append(m.Empty()))
    	})
    
    	t.Run("it has valid associativity", func(t *testing.T) {
    		t.Parallel()
    
    		a := monoid.SomeString("foo")
    		b := monoid.SomeString("bar")
    		c := monoid.NoneString()
    
    		// For all a, b and c in S, the equation (a • b) • c = a • (b • c) holds.
    		AssertEqual(t, a.Append(b).Append(c), a.Append(b.Append(c)))
    	})
    }
    

    The new iteration was changed a little to use foldable:

    func FizzBuzzFunctional(n int) string {
    	fizz := func(n int) bool {
    		return n%3 == 0
    	}
    
    	buzz := func(n int) bool {
    		return n%5 == 0
    	}
    
    	filters := foldable.RuleFoldable{
    		monoid.ForFizzBuzzPredicate(fizz, "Fizz"),
    		monoid.ForFizzBuzzPredicate(buzz, "Buzz"),
    	}
    
    	rules := fold(filters, monoid.NewEmptyFizzBuzzRuleset()) // a monoid which combines all the filters together
    
    	return monoid.FromStringOption(strconv.Itoa(n), rules(n))
    }
    
    // fold :: (Foldable t, Monoid m) => t m -> m
    func fold(filters foldable.RuleFoldable, m monoid.FizzBuzzRuleset) monoid.FizzBuzzRuleset {
    	rules := filters.Foldl(filters.Init(), func(result foldable.T, next foldable.T) foldable.T {
    		rule, ok := next.(func(int) monoid.OptionString)
    		mustOk(ok, "cannot cast result foldable.T to func(int) monoid.OptionString")
    
    		m = m.Append(rule)
    
    		return m
    	})
    
    	ruleSet, ok := rules.(monoid.FizzBuzzRuleset)
    	mustOk(ok, "cannot cast result foldable.T to monoid.FizzBuzzRuleset")
    
    	return ruleSet
    }
    
    func mustOk(ok bool, msg string) {
    	if !ok {
    		panic(msg)
    	}
    }
    

    Now that we have the generics, and your library we probably can come up with a better solution. I tried to use some of your ideas but at the moment you're changing the API faster than I have the time to follow :-D Nonetheless, I was almost able to implement the monoids I need from your wonderful library, however I stuck at the moment with a monoid to combine two functions. It got pretty ugly on my side.

    Could you please add an ExampleTest for this FizzBuzz case to demonstrate the usage of your library the way you were intended? What I really would like to achieve is the following translated into Go without being too ugly :)

    {-# LANGUAGE MonadComprehensions #-}
    
    module Main where
    import Data.Monoid (mappend)
    import Data.Maybe (fromMaybe, listToMaybe, maybe)
    import System.Environment (getArgs)
    
    
    fizzbuzz i = fromMaybe (show i) $ mappend ["fizz" | i `rem` 3 == 0]
                                              ["buzz" | i `rem` 5 == 0]
    
    main = mapM_ putStrLn [ fizzbuzz i | i <- [1..100] ]
    

    Thank you very much.

  • Update golang.org/x/exp digest to b4a6d95

    Update golang.org/x/exp digest to b4a6d95

    Mend Renovate

    This PR contains the following updates:

    | Package | Type | Update | Change | |---|---|---|---| | golang.org/x/exp | require | digest | 0b5c67f -> b4a6d95 |


    Configuration

    📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, click this checkbox.

    This PR has been generated by Mend Renovate. View repository job log here.

  • Update golang.org/x/exp digest to 0b5c67f

    Update golang.org/x/exp digest to 0b5c67f

    WhiteSource Renovate

    This PR contains the following updates:

    | Package | Type | Update | Change | |---|---|---|---| | golang.org/x/exp | require | digest | 39d4317 -> 0b5c67f |


    Configuration

    📅 Schedule: At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, click this checkbox.

    This PR has been generated by WhiteSource Renovate. View repository job log here.

  • Update golang.org/x/exp digest to 39d4317

    Update golang.org/x/exp digest to 39d4317

    WhiteSource Renovate

    This PR contains the following updates:

    | Package | Type | Update | Change | |---|---|---|---| | golang.org/x/exp | require | digest | bcd2187 -> 39d4317 |


    Configuration

    📅 Schedule: At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, click this checkbox.

    This PR has been generated by WhiteSource Renovate. View repository job log here.

  • Update golang.org/x/exp digest to bcd2187

    Update golang.org/x/exp digest to bcd2187

    WhiteSource Renovate

    This PR contains the following updates:

    | Package | Type | Update | Change | |---|---|---|---| | golang.org/x/exp | require | digest | a90fa8a -> bcd2187 |


    Configuration

    📅 Schedule: At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, click this checkbox.

    This PR has been generated by WhiteSource Renovate. View repository job log here.

  • Update module github.com/stretchr/testify to v1.7.1

    Update module github.com/stretchr/testify to v1.7.1

    WhiteSource Renovate

    This PR contains the following updates:

    | Package | Type | Update | Change | |---|---|---|---| | github.com/stretchr/testify | require | patch | v1.7.0 -> v1.7.1 |


    Release Notes

    stretchr/testify

    v1.7.1

    Compare Source


    Configuration

    📅 Schedule: At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, click this checkbox.

    This PR has been generated by WhiteSource Renovate. View repository job log here.

  • Update actions/cache action to v3

    Update actions/cache action to v3

    WhiteSource Renovate

    This PR contains the following updates:

    | Package | Type | Update | Change | |---|---|---|---| | actions/cache | action | major | v2 -> v3 |


    Release Notes

    actions/cache

    v3

    Compare Source


    Configuration

    📅 Schedule: At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, click this checkbox.

    This PR has been generated by WhiteSource Renovate. View repository job log here.

  • Update actions/setup-go action to v3

    Update actions/setup-go action to v3

    WhiteSource Renovate

    This PR contains the following updates:

    | Package | Type | Update | Change | |---|---|---|---| | actions/setup-go | action | major | v2 -> v3 |


    Release Notes

    actions/setup-go

    v3

    Compare Source


    Configuration

    📅 Schedule: At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, click this checkbox.

    This PR has been generated by WhiteSource Renovate. View repository job log here.

  • Update actions/checkout action to v3

    Update actions/checkout action to v3

    WhiteSource Renovate

    This PR contains the following updates:

    | Package | Type | Update | Change | |---|---|---|---| | actions/checkout | action | major | v2 -> v3 |


    Release Notes

    actions/checkout

    v3

    Compare Source


    Configuration

    📅 Schedule: At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, click this checkbox.

    This PR has been generated by WhiteSource Renovate. View repository job log here.

  • Configure Renovate

    Configure Renovate

    WhiteSource Renovate

    Welcome to Renovate! This is an onboarding PR to help you understand and configure settings before regular Pull Requests begin.

    🚦 To activate Renovate, merge this Pull Request. To disable Renovate, simply close this Pull Request unmerged.


    Detected Package Files

    • .github/workflows/test.yaml (github-actions)

    Configuration Summary

    Based on the default config's presets, Renovate will:

    • Start dependency updates only once this onboarding PR is merged
    • Enable Renovate Dependency Dashboard creation
    • If semantic commits detected, use semantic commit type fix for dependencies and chore for all others
    • Ignore node_modules, bower_components, vendor and various test/tests directories
    • Autodetect whether to pin dependencies or maintain ranges
    • Rate limit PR creation to a maximum of two per hour
    • Limit to maximum 20 open PRs at any time
    • Group known monorepo packages together
    • Use curated list of recommended non-monorepo package groupings
    • Fix some problems with very old Maven commons versions
    • Ignore spring cloud 1.x releases
    • Ignore http4s digest-based 1.x milestones
    • Use node versioning for @types/node
    • Limit concurrent requests to reduce load on Repology servers until we can fix this properly, see issue 10133

    🔡 Would you like to change the way Renovate is upgrading your dependencies? Simply edit the renovate.json in this branch with your custom config and the list of Pull Requests in the "What to Expect" section below will be updated the next time Renovate runs.


    What to Expect

    It looks like your repository dependencies are already up-to-date and no Pull Requests will be necessary right away.


    ❓ Got questions? Check out Renovate's Docs, particularly the Getting Started section. If you need any further assistance then you can also request help here.


    This PR has been generated by WhiteSource Renovate. View repository job log here.

  • Update module go to 1.19

    Update module go to 1.19

    Mend Renovate

    This PR contains the following updates:

    | Package | Type | Update | Change | |---|---|---|---| | go (source) | golang | minor | 1.18 -> 1.19 |


    Release Notes

    golang/go

    v1.19.3

    v1.19.2

    v1.19.1

    v1.19.0


    Configuration

    📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, check this box

    This PR has been generated by Mend Renovate. View repository job log here.

  • Update golang.org/x/exp digest to 8509921

    Update golang.org/x/exp digest to 8509921

    Mend Renovate

    This PR contains the following updates:

    | Package | Type | Update | Change | |---|---|---|---| | golang.org/x/exp | require | digest | b4a6d95 -> 8509921 |


    Configuration

    📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, check this box

    This PR has been generated by Mend Renovate. View repository job log here.

  • Update module github.com/stretchr/testify to v1.8.1

    Update module github.com/stretchr/testify to v1.8.1

    Mend Renovate

    This PR contains the following updates:

    | Package | Type | Update | Change | |---|---|---|---| | github.com/stretchr/testify | require | minor | v1.7.1 -> v1.8.1 |


    Release Notes

    stretchr/testify

    v1.8.1

    Compare Source

    v1.8.0

    Compare Source

    v1.7.5

    Compare Source

    v1.7.4

    Compare Source

    v1.7.3

    Compare Source

    v1.7.2

    Compare Source


    Configuration

    📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, check this box

    This PR has been generated by Mend Renovate. View repository job log here.

  • Dependency Dashboard

    Dependency Dashboard

    This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

    Open

    These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

    Detected dependencies

    github-actions
    .github/workflows/test.yaml
    • actions/setup-go v3
    • actions/checkout v3
    • actions/cache v3
    gomod
    go.mod
    • go 1.18
    • github.com/stretchr/testify v1.7.1
    • golang.org/x/exp v0.0.0-20220706164943-b4a6d9510983@b4a6d9510983

    • [ ] Check this box to trigger a request for Renovate to run again on this repository
  • Examples with functional monoids.

    Examples with functional monoids.

    Hello @genkami,

    Thank you for you detailed response and a great example. I also noticed you've updated the repo and added the FizzBuzz example:

    func main() {
    	monoid := option.DeriveMonoid[string](algebra.DeriveAdditiveSemigroup[string]())
    	fizzBuzz := func(i int) string {
    		fizz := option.Filter(option.Some[string]("Fizz"), func(_ string) bool { return i%3 == 0 })
    		buzz := option.Filter(option.Some[string]("Buzz"), func(_ string) bool { return i%5 == 0 })
    		return option.UnwrapOr(monoid.Combine(fizz, buzz), fmt.Sprint(i))
    	}
    	it := iterator.Map(iterator.Range[int](1, 15), fizzBuzz)
    	iterator.ForEach(it, func(s string) { fmt.Println(s) })
    }
    

    It looks nice, concise and pretty aligned with idiomatic Golang. What I'm not sure about is whether combining not monoids is ok, because they don't follow the monodic laws. Is it the expected behavior? In the example above you use a monoid to combine options which don't implement the Monoid interface.

    Allow me to drive it a little bit further: At the moment we have this Filter function on the option type. But what if (following the ideas from the aforementioned articles) we try to fold over a set of fizz-buzz Rules, where a Rule is function which takes a predicate and the word:

    type FizzBuzzPredicate func(num int) bool
    type FizzBuzzRule func(n int) option.String
    
    func Rule(p FizzBuzzPredicate, s string) FizzBuzzRule {
    	return func(n int) option.String {
    		if p(n) {
    			return option.Some(s)
    		}
    
    		return option.NoneString()
    	}
    }
    
    func FizzBuz(n int) string {
    	fizz := func(n int) bool {
    		return n%3 == 0
    	}
    
    	buzz := func(n int) bool {
    		return n%5 == 0
    	}
    
    	// rules should be a foldable of monoids
    	rules := []FizzBuzzRule{
    		Rule(fizz, "Fizz"),
    		Rule(buzz, "Buzz"),
    	}
    
    	// ruleSet is a monoid, which is a function by its nature: monoid[FizzBuzzRule]
    	// Written in a move verbose way it is the same as: monoid[ func(n int) option.String].
            // see https://blog.ploeh.dk/2017/11/06/function-monoids/
    	ruleSet := fold(rules)
    
    	return ruleSet(n).UnwrapOr(strconv.ItoA(i))
    }
    
    // fold :: (Foldable t, Monoid m) => t m -> m
    func Fold(filters Foldable) monoid[FizzBuzzFilter] {
      // fold over filters and turn them into a monoid
    }
    

    An excerpt in Haskell:

    fizzbuzz i = fromMaybe (show i) (ruleSet i)
    ruleSet = fold rules
    

    The reasoning behind this is is as such:

    • Option should probably not have the Filter method, or should it? I've added it for convenience :)
    • Monoids could be the functions per sei, so the combine method should be able to join the function together into a single monoid.

    Tell me what do you think?

    Thank you for your wonderful job and for patience!

    PS: I'm writing without an IDE at hand, so forgive me for some inconsistencies.

Helpfully Functional Go like underscore.js

/\ \ __ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ __ __

Dec 22, 2022
Functional tools in Go 1.18 using newly introduced generics

functools functools is a simple Go library that brings you your favourite functi

Dec 5, 2022
Experimenting with golang generics to implement functional favorites like filter, map, && reduce.

funcy Experimenting with golang generics to implement functional favorites like filter, map, && reduce. 2021-12 To run the tests, you need to install

Dec 29, 2021
Utilities and immutable collections for functional programming in Golang

Utilities and immutable collections for functional programming in Golang. This is an experimental library to play with the new Generics Feature in Go 1.18.

Sep 1, 2022
A collection of functional operators for golang with generics

fn fn is a collection of go functional operators with generics Getting Started P

Jul 8, 2022
F - Experimenting with Go 1.18 generics to write more functional Go code

f f is a simple library that leverages the new generics in Golang to create a tools for functional style of code. Pipe like '|>' in Elixir or Elm. inp

Apr 12, 2022
libraries for various programming languages that make it easy to generate per-process trace files that can be loaded into chrome://tracing
libraries for various programming languages that make it easy to generate per-process trace files that can be loaded into chrome://tracing

chrometracing: chrome://tracing trace_event files The chrometracing directory contains libraries for various programming languages that make it easy t

Oct 6, 2022
A collection of small Go utilities to make life easier.

The simplego package provides a collection of Go utilities for common tasks.

Jan 4, 2023
The easiest way to make API documents for GraphQL

Document Generator for GraphQL gqldoc is now alpha gqldoc is command line tool to generate documents from GraphQL schema or your GraphQL endpoint. the

Dec 20, 2022
make slice items unique in go

make slice items unique in go

Jan 20, 2022
How much you spend for glovo. Make config file and launch yourself

how_much_you_spend How much you spend for glovo. Make config file and launch yourself, you are welcome! Put config file in the same folder as executab

Nov 9, 2021
Code Generation for Functional Programming, Concurrency and Generics in Golang

goderive goderive derives mundane golang functions that you do not want to maintain and keeps them up to date. It does this by parsing your go code fo

Dec 25, 2022
Several functional programming supporting in golang

A golang library that makes operations on slice easilier What can I do? slice process Map Filter Sort Reverse map process Keys Values output (starting

Jun 27, 2022
End to end functional test and automation framework
End to end functional test and automation framework

Declarative end to end functional testing (endly) This library is compatible with Go 1.12+ Please refer to CHANGELOG.md if you encounter breaking chan

Jan 6, 2023
Functional programming library for Go including a lazy list implementation and some of the most usual functions.

functional A functional programming library including a lazy list implementation and some of the most usual functions. import FP "github.com/tcard/fun

May 21, 2022
An always-on framework that performs end-to-end functional network testing for reachability, latency, and packet loss

Arachne Arachne is a packet loss detection system and an underperforming path detection system. It provides fast and easy active end-to-end functional

Dec 31, 2022
Helpfully Functional Go like underscore.js

/\ \ __ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ __ __

Dec 22, 2022
vcluster - Create fully functional virtual Kubernetes clusters - Each cluster runs inside a Kubernetes namespace and can be started within seconds
vcluster - Create fully functional virtual Kubernetes clusters - Each cluster runs inside a Kubernetes namespace and can be started within seconds

Website • Quickstart • Documentation • Blog • Twitter • Slack vcluster - Virtual Clusters For Kubernetes Lightweight & Low-Overhead - Based on k3s, bu

Jan 4, 2023
The package manager for macOS you didn’t know you missed. Simple, functional, and fast.
The package manager for macOS you didn’t know you missed. Simple, functional, and fast.

Stew The package manager for macOS you didn’t know you missed. Built with simplicity, functionality, and most importantly, speed in mind. Installation

Mar 30, 2022
functional programming in go

function programming experimental lib why another fp lib I like fp style and I haven’t found a lib with these features: streamingly, I can handle infi

Sep 1, 2022