Created
September 24, 2018 12:51
-
-
Save nikcorg/1b419070b239b861df8e59d3652343b3 to your computer and use it in GitHub Desktop.
Playing with Maybe in Go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"strings" | |
) | |
type Any interface{} // The lack of generics in Go is the pitfall | |
type Morphism func(Any) Any | |
type Option interface { | |
Map(Morphism) Option | |
Alt(Option) Option | |
IsSome() bool | |
IsNone() bool | |
Get() Any | |
Chain(func(Any) Option) Option | |
} | |
func FromNullable(x Any) Option { | |
if x == nil { | |
return None{} | |
} else { | |
return Some{x} | |
} | |
} | |
type Some struct { | |
Value Any | |
} | |
func (x Some) Map(f Morphism) Option { | |
return Some{f(x.Value)} | |
} | |
func (x Some) Chain(f func(Any) Option) Option { | |
return f(x.Get()) | |
} | |
func (x Some) Alt(_ Option) Option { | |
return x | |
} | |
func (x Some) Get() Any { | |
return x.Value | |
} | |
func (x Some) IsSome() bool { return true } | |
func (x Some) IsNone() bool { return false } | |
type None struct { | |
} | |
func (x None) Map(f Morphism) Option { | |
return x | |
} | |
func (x None) Chain(_ func(Any) Option) Option { | |
return x | |
} | |
func (x None) Alt(o Option) Option { | |
return o | |
} | |
func (x None) Get() Any { | |
return nil | |
} | |
func (x None) IsSome() bool { return false } | |
func (x None) IsNone() bool { return true } | |
func upper(x Any) Any { | |
// The abomination that is the next line is 💩 | |
// Without generics you can't have nice things | |
return Any(strings.ToUpper(x.(string))) | |
} | |
func constNil(x Any) Any { | |
return nil | |
} | |
func main() { | |
x := FromNullable("hello") | |
y := x.Map(upper) | |
z := y.Map(constNil).Chain(FromNullable) | |
fmt.Printf("isNone=%t, isSome=%t, val=%v\n", x.IsNone(), x.IsSome(), x.Get()) | |
fmt.Printf("isNone=%t, isSome=%t, val=%v\n", y.IsNone(), y.IsSome(), y.Get()) | |
fmt.Printf("isNone=%t, isSome=%t, val=%v\n", z.IsNone(), z.IsSome(), z.Get()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment