4 ms·
`Either` works pretty well in Go. I implemented it and it felt reasonably close to Rust/Haskell (without `try!` of course).
by charlieflowers 3y ago
`Either` works pretty well in Go. I implemented it and it felt reasonably close to Rust/Haskell (without `try!` of course).
- 12345hn6789 3y agoEither is nearly in the language anyways. The vast majority of pragmatic go functions will return [Result, Error] and or just [Error]. We are only missing support to treat this as a monad.
- corethree 3y agoYou don't need support. Monad composition isn't a special feature it can be implemented directly. Not an expert in Go but I think you can do this: func compose[A any, B any, C any](a func(A) (B, error), b func(B) (C, error)) func(A) (C, error) { return func(aInp A) (C, error) { res, err := a(aInp) if err == nil { return b(res) } else { return *new(C), err } } } The above is equivalent to haskells fish operator >=> The bind operator (>>=) can be implimented in terms of composition: func bind[A any, B any, C any](a func(A) (B, error), b func(B) (C, error), aInput A) (C, error) { return compose[A, B, C](a, b)(aInput) }
- kadoban 3y agoEither as a pattern is _used_ everywhere, but the standard library in go doesn't have one (people just use a tuple), so it's _always_ encoded wrong. It's very annoying.
- corethree 3y agoThere is no tuple type in go. When you see a func() (A, error) that is not a function returning a tuple. It is a function returning two values that cannot be composed. You can't A(B()) if B returns two values. It's pure comedy.
- deleted 3y ago[deleted]
- duskwuff 3y ago> You can't A(B()) if B returns two values. You can if A is a function which takes two arguments, e.g. package main import "log" func A(x, y int) { log.Printf("%d, %d", x, y) } func B() (int, int) { return 1, 2 } func main() { A(B()) } https://go.dev/play/p/Jp4B0L6NJj2 https://go.dev/play/p/Jp4B0L6NJj2
- erik_seaberg 3y agoWhat you can't do is a(b(), c()) unless b and c return single values. And there are no slices or channels of tuples, return values must be destructured right away.
- deleted 3y ago[deleted]
- eweise 3y agoTo me, the problem is that Go returns two values which makes it hard to compose functions.
- sambeau 3y agoThat's deliberate to stop you trying to compose functions that return errors. You should be explicitly handling the errors before you compose.
- eweise 3y agogreat, except 99% of the time I want to handle the error by bubbling it up to a top level routine. From my experience, "handling" the error means wrapping it in another error and returning, which is what you get from other languages for free.
- KingOfCoders 3y agoI don't think you should bolt every concept into every language. One USP of Go is how dead simple it is to learn and how fast it compiles (because it is dead simple - compare it to Rust compile times). I did a lot of Lisp and Haskell, scaled a startup on FP Scala code and sold it. I did put Option everywhere. In the 2000s I came up with the Iterable hack for Option<> in Java public abstract class Option[T] implements Iterable[T] { } // Some then is a one element Iterator/ None is an empty iterator // With for you then can do something on Some // orElse left as an exercise to the reader for (String name: option) { // do something with name } but today I think one should embrace the language and if it does not work for you, use something else. For Go I think something like Zigs !i32 would fit in perhaps, if one wants a higher level of error handling.
- charlieflowers 3y agoI agree about cramming features across languages. Plus, Software dev is social. I only did this in code for myself. That being said though, it actually fit really well in golang. Allowed functions that used to return ‘null, err’ to return an Either, which improved on all the downsides of returning null (if you return null your callers have to check for it). It actually improved the ergonomics quite a bit. ‘Either’ fits nicely into golang, but I doubt it will become mainstream anytime soon.