Skip to content

Instantly share code, notes, and snippets.

@Rubentxu
Created September 24, 2015 23:34
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Rubentxu/c353cac8f18321dbd96d to your computer and use it in GitHub Desktop.
Save Rubentxu/c353cac8f18321dbd96d to your computer and use it in GitHub Desktop.
Implementing the Maybe monad in Golang
package main
import (
"fmt"
"errors"
)
type Maybe interface {
Return(value interface{}) Maybe
Bind(func(interface{}) Maybe) Maybe
}
type Just struct {
Value interface{}
}
type Nothing struct {}
func (j Just) Return(value interface{}) Maybe {
return Just{ value }
}
func (j Just) Bind(fn func(interface{}) Maybe) Maybe {
return fn(j.Value)
}
func (n Nothing) Return(value interface{}) Maybe {
return Nothing{}
}
func (n Nothing) Bind(fn func(interface{}) Maybe) Maybe {
return Nothing{}
}
// Now instead of writing things like this
func ErroringDouble(a int) (int, error) {
return 2 * a, errors.New("This is what bothers me about Go the most, I think.")
}
// We can write
func MaybeDouble(a Maybe) Maybe {
return a.Bind(func (v interface{}) Maybe {
return Just { 2 * v.(int) }
})
}
// Although it certainly isn't as clear as the first definition, and we
// basically had to throw type safety out the window, we no longer
// have to write code like the following:
/*
// Double a number three times because demonstrations, okay?
a := 2
newA1, err := ErroringDouble(a)
if err != nil {
fmt.Println("Whoops!")
} else {
newA2, err2 := ErroringDouble(newA1)
if err2 != nil {
fmt.Println("Whoops!!")
} else {
newA3, err3 := ErroringDouble(newA3)
if err3 != nil {
fmt.Println("Whoops!!!")
} else {
// Finally do something with newA3
}
}
}
*/
// We can instead write...
/*
a := Just{ 2 }
newA := MaybeDouble(MaybeDouble(MaybeDouble( a )))
newA.bind(func (v interface{}) Maybe) {
// Do stuff with our new value
})
*/
func main() {
val := Just{ 3 }
fmt.Println(val.Bind(func (v interface{}) Maybe {
value := v.(int)
return Just{ value * value }
}).Bind(func (v interface{}) Maybe {
return Nothing{}
}).Bind(func (v interface{}) Maybe {
return Just{ v.(int) + 1 }
}))
fmt.Println(MaybeDouble(MaybeDouble(MaybeDouble(val))))
}
@Globidev
Copy link

Please don't

@ryukinix
Copy link

ryukinix commented Mar 3, 2018

Please do it.

@anboo
Copy link

anboo commented May 29, 2018

Please, do it +

@behrangsa
Copy link

Please don't Go

@politrons
Copy link

politrons commented May 27, 2019

Yes!, now lets go with Try!!, and then Either 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment