Live data from Hacker News

Leveraging the Go Type System

gopherguides.com

71–80 of 112 posts

Re: Leveraging the Go Type System

#71

Earlier quoted context omitted.

I don't mind that the compiler doesn't provide a default string implementation by default. I'm happy to use string values in my enums (in most cases const string vs int doesn't matter much for performance) for convenience; what I do wish for is full-blown ADTs. I want to be able to express `'Hello' | 'World' | 42 | struct{Name string, Age int} | []int` and know that the compiler will enforce. You can sort of get ther…

Do you have any examples of how you would implement a makeshift sum type like your example?

    X interface{} // int(3) | int(5) | []float64 | *Z
It sucks.

Re: Leveraging the Go Type System

#72

Earlier quoted context omitted.

> Then, you can define your categories normally: > var ( > Adventure = genre.New(1, "Adventure") > Comic = genre.New(2, "Comic") > // etc > ) Yet there is nothing preventing anyone from reassigning Adventure to genre.New(2, "Comic") or some other arbitrary value. The fact that golang doesn't have the equivalent of Java's `final` is just poor design.

> The fact that golang doesn't have the equivalent of Java's `final` is just poor design. That Java dropped C++-style `const` is also poor design. We're just all really bad at this.

C++'s const has some issues, so I can see why. Plus, it's possible to design around it by means of immutable data structures (e.g. see Scala).

I think that Rust's approach is superior to C++'s here, but even that has some issues so they have to retort to interior mutability via RefCell.

Re: Leveraging the Go Type System

#73
post #56

Earlier quoted context omitted.

> Then, you can define your categories normally: > var ( > Adventure = genre.New(1, "Adventure") > Comic = genre.New(2, "Comic") > // etc > ) Yet there is nothing preventing anyone from reassigning Adventure to genre.New(2, "Comic") or some other arbitrary value. The fact that golang doesn't have the equivalent of Java's `final` is just poor design.

There's nothing preventing someone from editing the source code to `const Comic = Adventure` either. Either you have access to edit String() AND have access to mess with the definitions in source code, or you don't have access to either. The idea that `final` can protect you against yourself is kinda silly IMHO.

Think about the use case of a library import. In golang, the user has the ability to change library "constants", wreaking havoc in the process.

Secondly, `final` serves as strong and clear documentation. We know just from looking at the definition that this is variable is not going to be re-bound.

On a side note, this compiles in golang:

    func main() {
        true := false
    
        if !true {
        fmt.Println("wat")
        }
    }

Re: Leveraging the Go Type System

#74
post #19

I had heard that the Go type system was just annoying and too simple to be useful, and this blog post has convinced me that that is 100% true.

It might be a little premature to judge an entire language on an introduction article for beginners. This article isn't intended to show every possible way Go can solve a problem, but intended to show people new to Go different ways to think about types. In a production scenario, it's unlikely I would use this solution. This is really an "academic" exercise in types for Go, not a practical application.

My reply was at least partially facetious as this wasn't my first exposure to Go. If you like the simplicity of Go's type system I can't argue with that, but I do think your article demonstrates the way that simplicity at the language level pushes complexity into the users code. Pick any modern statically typed language and this whole post will boil down to something like:

  data Genre = Adventure
             | Comic
             | Crime
             | ...
             deriving (Show)

Re: Leveraging the Go Type System

#76
post #4

For an example with Go generation and using iota see stringer[0] and Rob Pike's related blog post[1] [0] https://pkg.go.dev/golang.org/x/tools/cmd/stringer [1] https://blog.golang.org/generate

Perhaps the Golang managers would do well to elevate stringer into their suite of supported commands:

https://golang.org/cmd/

Re: Leveraging the Go Type System

#77
post #56

Earlier quoted context omitted.

There's nothing preventing someone from editing the source code to `const Comic = Adventure` either. Either you have access to edit String() AND have access to mess with the definitions in source code, or you don't have access to either. The idea that `final` can protect you against yourself is kinda silly IMHO.

Think about the use case of a library import. In golang, the user has the ability to change library "constants", wreaking havoc in the process. Secondly, `final` serves as strong and clear documentation. We know just from looking at the definition that this is variable is not going to be re-bound. On a side note, this compiles in golang: func main() { true := false if !true { fmt.Println("wat") } }

I mean, at some point, garbage in garbage out, no? For example, in javascript, you can do `Array.prototype.map = null`, in C you can do `#define if while`, etc.

It's highly unidiomatic to mutate bindings from libraries in any language, even ones that technically allow you to, so the observation that go is one of those languages feels like nitpicking at obscurities.

My Java is rusty, but I recall that several years ago I ran into some stuff in the Java core API that was needlessly marked final requiring some nasty wrapping around a huge class to get around. Trade-offs, trade-offs.

Re: Leveraging the Go Type System

#78

Earlier quoted context omitted.

I don't mind that the compiler doesn't provide a default string implementation by default. I'm happy to use string values in my enums (in most cases const string vs int doesn't matter much for performance) for convenience; what I do wish for is full-blown ADTs. I want to be able to express `'Hello' | 'World' | 42 | struct{Name string, Age int} | []int` and know that the compiler will enforce. You can sort of get ther…

Do you have any examples of how you would implement a makeshift sum type like your example?

Here's one such workaround: https://play.golang.org/p/4Fd7aKRtmvz

It's not great for a number of reasons. First of all, `nil` is always a valid permutation even if we don't want it to be. Secondly, it's a lot of work to express the constraints we want. Thirdly, it's not perfectly type-safe; someone who was determined to shoot themselves in the foot could construct other instances of our "singleton types" if they really wanted to. Fourthly, boxing all of these values will almost certainly cause unnecessary allocations which would be a bummer if we wanted to create a lot of these quickly (this is an implementation detail and may not be any worse than a language with first-class support for sum types).

Re: Leveraging the Go Type System

#79

Earlier quoted context omitted.

Do you have any examples of how you would implement a makeshift sum type like your example?

X interface{} // int(3) | int(5) | []float64 | *Z It sucks.

We can recoup a fair bit more type safety than this if we're interested in going through the effort: https://play.golang.org/p/4Fd7aKRtmvz. See my sibling comment for more details.
Post reply on HN