warp

package module
v0.0.17 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 30, 2024 License: MIT Imports: 1 Imported by: 1

README

warp

warp is an experimental Go library that leverages generics to introduce monadic abstractions, enabling functional programming patterns for improved error handling and composition of asynchronous operations.

Features

  • Result Monad: Represents computations yielding a result or error, useful for chaining operations with error handling.
  • Event Monad: Allows working with time-based events in a functional style.
  • Applicative and Functor Patterns: Supports functional programming paradigms within Go’s type-safe generics.

Installation

To install warp, run:

go get github.com/tetsuo/warp

Usage

Result

The Result type encapsulates a computation that may return a value or an error, allowing you to chain dependent operations with error handling:

package main

import (
    "context"
    "errors"
    "fmt"
    "math"

    "github.com/tetsuo/warp"
    "github.com/tetsuo/warp/result"
)

var errNegativeSqrt = errors.New("negative square root")

func sqrt(x float64) warp.Result[float64] {
    if x < 0 {
        return result.Error[float64](errNegativeSqrt)
    }
    return result.Ok(math.Sqrt(x))
}

func main() {
    res := result.Chain(sqrt(16), sqrt)
    value, err := res(context.Background())
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Result:", value)
    }
}

Output:

Result: 2

If you attempt to compute the square root of a negative number:

res := result.Chain(sqrt(-1), sqrt)
value, err := res(context.Background())

Output:

Error: negative square root
Event

The Event monad models time-based events, allowing for declarative composition of asynchronous or periodic operations. Here's an example demonstrating how to use the Event monad to process a stream of integers, doubling each value and summing them up:

package main

import (
    "context"
    "fmt"

    "github.com/tetsuo/warp/event"
)

func main() {
    // Create an event from a slice of integers
    numbers := event.From([]int{1, 2, 3, 4, 5})

    // Define a function to double each number
    double := func(n int) int {
        return n * 2
    }

    // Define a function to sum two numbers
    add := func(a, b int) int {
        return a + b
    }

    // Map the 'double' function over the event
    doubledNumbers := event.Map(numbers, double)

    // Fold the doubled numbers into a single sum
    sum := event.Fold(doubledNumbers, 0, add)

    // Create a channel to receive the result
    resultChan := make(chan int)

    // Start the event processing
    go sum(context.Background(), resultChan)

    // Read and print the result
    for result := range resultChan {
        fmt.Printf("The sum of doubled numbers is: %d\n", result)
    }
}

Output:

The sum of doubled numbers is: 2
The sum of doubled numbers is: 6
The sum of doubled numbers is: 12
The sum of doubled numbers is: 20
The sum of doubled numbers is: 30

In this example, we create an event from a slice of integers, double each number using the Map function, and then use Fold to produce a running sum of the doubled numbers. Each intermediate result is processed asynchronously and printed to the console.

License

MIT License. See LICENSE for details.

Documentation

Overview

Package warp provides experimental monads.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Event

type Event[A any] func(context.Context, chan<- A)

An Event represents a collection of discrete occurrences of events with associated values.

Example
package main

import (
	"context"
	"fmt"

	"github.com/tetsuo/warp/event"
)

func main() {
	dequeue := event.Fold(
		event.Map(event.From([]int{1, 2, 3}), double),
		0,
		add,
	)

	r := make(chan int)

	go dequeue(context.TODO(), r)

	for i := range r {
		fmt.Println(i)
	}

}

func double(n int) int {
	return n * 2
}

func add(b, a int) int {
	return b + a
}
Output:
2
6
12

type Future

type Future[A any] Event[Result[A]]

A Future represents a collection of discrete occurrences of events with associated values or errors, in that, a Future is actually an Event that may fail and emits a value which is encapsulated in a Result.

type IO

type IO[A any] func() A

An IO represents a computation that never fails and yields a value of type A.

type Nilable

type Nilable[A any] *A

A Nilable represents an optional value which is either some value or nil.

type Predicate

type Predicate[A any] func(A) bool

A Predicate represents a predicate (boolean-valued function) of one argument.

type Result

type Result[A any] func(context.Context) (A, error)

A Result represents a result of a computation which is either a value of type A, or an error.

Example
package main

import (
	"context"
	"errors"
	"fmt"

	"github.com/tetsuo/warp"
	"github.com/tetsuo/warp/result"
)

func main() {
	errEmptySlice := errors.New("empty slice")

	// head returns the first value contained in a slice, or fails with
	// an empty slice error.
	head := func(as []float64) warp.Result[float64] {
		if len(as) == 0 {
			return result.Error[float64](errEmptySlice)
		}
		return result.Ok(as[0])
	}

	errDivByZero := errors.New("cannot divide by zero")

	// inverse returns an inverse of a number, or fails with
	// division by zero error if 0 is encountered.
	inverse := func(n float64) warp.Result[float64] {
		if n == 0 {
			return result.Error[float64](errDivByZero)
		}
		return result.Ok(1 / n)
	}

	double := func(n float64) float64 {
		return n * 2
	}

	check := func(nums []float64) string {
		return result.Reduce(
			context.Background(),
			result.Chain(
				// double first number
				result.Map(head(nums), double),
				// take its inverse
				inverse,
			),
			// error handler
			func(err error) string {
				return fmt.Sprintf("Error is %v", err)
			},
			// success handler
			func(head float64) string {
				return fmt.Sprintf("Result is %.3f", head)
			},
		)
	}

	fmt.Println(check([]float64{24, 25, 26}))

	fmt.Println(check([]float64{0, 1, 2}))

	fmt.Println(check([]float64{}))

}
Output:
Result is 0.021
Error is cannot divide by zero
Error is empty slice

Directories

Path Synopsis
Package event implements the Event type.
Package event implements the Event type.
Package future implements the Future type.
Package future implements the Future type.
Package io implements the IO type.
Package io implements the IO type.
Package nilable implements the Nilable type.
Package nilable implements the Nilable type.
Package result implements the Result type.
Package result implements the Result type.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
⌂ 换网址