Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
101 lines (77 sloc) 3.2 KB

GoDoc Build Status

maybe – A Maybe monad experiment for Go

Description

This package implements the Maybe monad for a couple basic types and arrays of those types. This allows "boxing" a value or error and chaining operations on the boxed type without constant error checking. See "Error Handling in Go: Rob Pike Reinvented Monads" for more on the concept.

This is an experiment to simplify some libraries the author is writing. It should not be considered stable for production use.

To keep type names short and manageable, abbreviations are used. Type maybe.I is for ints; maybe.AoI is short for "array of ints" and maybe.AoAoI is short for "array of array of ints".

This package only implements up to 2-D containers because those are common when working with line-oriented data. For example, a text file can be interpreted as an array of an array of characters.

Three constructors are provided for each type. The Just_ and Err_ constructors are for values and errors, respectively. The New_ constructor can construct either type, and is intended for wrapping functions that follow the pattern of returning a value and an error.

Example

package maybe_test

import (
	"fmt"
	"strconv"

	"github.com/xdg/maybe"
)

type example struct {
	label string
	data  []string
}

// Example shows how to convert a list of strings to a list of non-negative
// integers, accounting for the possibility of failure either in conversion
// or validation.
func Example() {

	cases := []example{
		{label: "success", data: []string{"23", "42", "0"}},
		{label: "bad atoi", data: []string{"23", "forty-two", "0"}},
		{label: "negative", data: []string{"23", "-42", "0"}},
	}

	// Function to convert string to maybe.I.
	atoi := func(s string) maybe.I { return maybe.NewI(strconv.Atoi(s)) }

	// Function to validate non-negative integer.
	validate := func(x int) maybe.I {
		if x < 0 {
			return maybe.ErrI(fmt.Errorf("%d is negative", x))
		}
		return maybe.JustI(x)
	}

	// For each example, try converting and validating functionally and
	// then inspecting the result.
	for _, c := range cases {
		// Wrap the []string in a maybe type.
		strs := maybe.JustAoS(c.data)

		// Functionally convert and validate.
		nums := strs.ToInt(atoi).Map(validate)

		// Check if it worked.
		if nums.IsErr() {
			fmt.Printf("%s: %v failed to convert: %v\n", c.label, strs, nums)
		} else {
			fmt.Printf("%s: %v converted to %v\n", c.label, strs, nums)
		}
	}

	// Output:
	// success: Just [23 42 0] converted to Just [23 42 0]
	// bad atoi: Just [23 forty-two 0] failed to convert: Err strconv.Atoi: parsing "forty-two": invalid syntax
	// negative: Just [23 -42 0] failed to convert: Err -42 is negative
}

Copyright and License

Copyright 2017 by David A. Golden. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License"). You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0