Skip to content

Instantly share code, notes, and snippets.

@lispyclouds
Created December 9, 2020 10:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lispyclouds/bd212d177817061cddc1dec75849bd7d to your computer and use it in GitHub Desktop.
Save lispyclouds/bd212d177817061cddc1dec75849bd7d to your computer and use it in GitHub Desktop.
Attempt at monadic Go
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
type Result interface {
unwrap() int
String() string
}
type Success struct {
value int
}
func (s Success) unwrap() int {
return s.value
}
func (s Success) String() string {
return strconv.Itoa(s.value)
}
type Failure struct {
err string
}
func (s Failure) unwrap() int {
panic("holy fuck")
}
func (s Failure) String() string {
return "Error: " + s.err
}
type effectFnType func(int) (int, error)
func readAndAdd(prev int) (int, error) {
print("Enter a number: ")
in := bufio.NewScanner(os.Stdin)
in.Scan()
n, err := strconv.Atoi(in.Text())
return n + prev, err
}
func bind(m Result, nextFn effectFnType) Result {
switch m.(type) {
case Failure:
return m
default:
result, err := nextFn(m.unwrap())
if err != nil {
return Failure{err: err.Error()}
} else {
return Success{value: result}
}
}
}
func chain(init int, effects ...effectFnType) Result {
result := bind(Success{value: init}, effects[0])
for i := 1; i < len(effects); i++ {
result = bind(result, effects[i])
}
return result
}
func main() {
result := chain(0, readAndAdd, readAndAdd, readAndAdd)
fmt.Println(result)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment