https://github.com/tttardigrado/goadt
Algebraic Data Types generator for the Go programming language
https://github.com/tttardigrado/goadt
adt algebraic-data-types code-generator functional-go functional-programming go-generate golang golang-tools haskell
Last synced: about 2 months ago
JSON representation
Algebraic Data Types generator for the Go programming language
- Host: GitHub
- URL: https://github.com/tttardigrado/goadt
- Owner: tttardigrado
- License: mit
- Created: 2023-01-23T13:24:40.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2023-01-26T13:48:31.000Z (over 2 years ago)
- Last Synced: 2024-07-30T18:34:42.537Z (10 months ago)
- Topics: adt, algebraic-data-types, code-generator, functional-go, functional-programming, go-generate, golang, golang-tools, haskell
- Language: Haskell
- Homepage:
- Size: 5.29 MB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.md
Awesome Lists containing this project
README
# GoADT


Algebraic data types generator for the Go programming language

## Tech stack
* Haskell
* Golang
* Parsec
* CmdArgs
* Go-Sumtypes## Product types
A product type `A x B` is a compounded type that combines one element from each of the types. According to the Curry-Howard isomorphism, it corresponds to the `AND` operation in intuitionistic logic.In golang, we are going to represent product types as `structs`.
```haskell
-- haskell
data Tuple a b = Tuple
{ x :: a
, y :: b
}
``````go
// golang
type Tuple[A, B any] struct {
x A
y B
}
```## Sum types
A sum type `A + B` is a compounded type that requires one element from one of the types. According to the Curry-Howard isomorphism, it corresponds to the `OR` operation in intuitionistic logic.In golang, we are going to represent product types as `interfaces`
```haskell
-- haskell
data Either a b
= Left a
| Right b
```
```go
// go
type Either[A, B any] infterface {
implEither()
}type Left[A, B any] struct { a A }
func (_ Left) implEither() {}type Right[A, B any] struct { b B }
func (_ Right) implEither() {}
```## Using ADTs
Let's start with an example of an ADT: `Opt`. This type represents the possibility of the non-existence of a value (in Haskell it's known as `Maybe`, but we will define an isomorphic `Opt` type)
```haskell
-- haskell
data Opt a
= None
| Some a
```
```go
// go
type Opt[A any] interface { implOpt() }// Data Constructors Structs
type Some[A any] struct { V A }
type None[A any] struct { }// Implement the interface
func (_ Some[A]) implOpt() { }
func (_ None[A]) implOpt() { }// Constructors
func NewSome[A any](V A) Opt[A] { return Some[A]{ V: V } }
func NewNone[A any]( ) Opt[A] { return None[A]{ } }
```Now, let's see how to use it. In most functional programming languages (like Haskell, Ocaml and SML) ADTs can be used with `pattern matching`, but, unfortunately, go does not have that feature. The closest analog is a `type switch`.
```haskell
-- haskell
map :: (a -> r) -> Opt a -> Opt r
map fn (Some v) = Some $ fn v
map fn None = None
``````go
// go
func Map[A, R any](fn func(A) R, opt Opt[A]) (res Opt[R]) {
switch t := opt.(type) {
case Some[A]: res = NewSome(fn(t.V))
case None[A]: res = NewNone[R]()
}
return
}
```If you build your functions this way, [go-sumtype](https://github.com/BurntSushi/go-sumtype) can be used to check for the exhaustiveness of the type switches.
## Using GoADT
Check the [examples](./examples/) directory to see how one could use `goadt` and `go generate` to automatically generate ADTs## References:
1. [Go and Algebraic data types](https://eli.thegreenplace.net/2018/go-and-algebraic-data-types/) by Eli Bendersky
2. [Sum Types in Go](https://www.jerf.org/iri/post/2917/) by Jeremy Bowers
3. [Golang Tips #1: ADT](https://rguilmont.net/blog/2022-02-20-golang-generics-options/) by Romain Guilmont
4. [Alternatives to sum types in Go](https://making.pusher.com/alternatives-to-sum-types-in-go/) by Will Sewell
5. [Wikipedia's](https://en.wikipedia.org/wiki/Algebraic_data_type) article on ADTs
6. [Algebraic Data Types in Haskell](https://serokell.io/blog/algebraic-data-types-in-haskell) by Gints Dreimanis
7. [Why algebraic data types are important](https://www.youtube.com/watch?v=LkqTLJK2API) by Bartosz Milewski
8. [go-sumtype](https://github.com/BurntSushi/go-sumtype) an exhaustiveness checker for sum types by Andrew Gallant