DEV Community

loading...

Implementing Maybe in Go

yujiri8 profile image Ryan Westlund ・2 min read

Go doesn't have sum types. (Interfaces are not sum types since they require at least one common method, and interface{} sacrifices type checking.) That means it can't implement something equivalent to Maybe from Haskell... or does it?

Today it occurred to me how it can be done just as I was about to write that it was impossible. (Of course, the lack of generics means we can only have a Maybe restricted to a specific type, but still.) It turns out you can implement a sum type in Go. It's both hacky and clunky, but it can be done.

package main

import (
    "fmt"
    "strconv"
)

type MaybeInt interface {
    // A dummy method to make sure other types don't typecheck as a MaybeInt.
    MakeMaybe()
}

type NothingInt struct {
}

func (NothingInt) MakeMaybe() {}

type JustInt struct {
    Val int
}

func (JustInt) MakeMaybe() {}

func main() {
    var x = NothingInt{}
    var y = JustInt{5}
    fmt.Println(showMaybeInt(x), showMaybeInt(y))
    fmt.Println(fromJust(y))
    fmt.Println(fromJust(x))
}

func showMaybeInt(mi MaybeInt) string {
    switch i := mi.(type) {
    case NothingInt:
        return "nothing"
    case JustInt:
        return strconv.Itoa(i.Val)
    }
    return ""
}

// Like the fromJust in Haskell's Data.Maybe, which assumes a Maybe value is a Just and errors if it's not.
func fromJust(mi MaybeInt) int {
    return mi.(JustInt).Val
}
Enter fullscreen mode Exit fullscreen mode

This code still typechecks that a MaybeInt value is either a NothingInt or JustInt, since nothing else implements the interface, but you can have a function that accepts two totally different types. Fundamentally, this achieves the benefit that Maybe has over interface{}.

So is this a good idea? Is it even worth all that icky code? Probably not, but I thought it was interesting that it can be done.

Discussion (0)

pic
Editor guide