Earlier quoted context omitted.
>A sum type `T = A | B` means that a value of type `T` can be either of type `A` or of type `B`. Such a type is used to express polymorphism. Taking this example (in English / pseudocode): Define a class Animal. Define Dog as a subclass of Animal. Define Cat as a subclass of Animal. Case 1) Now if we have a variable a1 that can, at runtime, contain (or refer to) either a Dog or an Animal instance. Case 2) And if we h…
I'm thinking you just violated the Liskov substitution principle ( https://en.wikipedia.org/wiki/Liskov_substitution_principle ). A sum type is the same thing as a tagged union, a variant record, or a discriminated union ( https://en.wikipedia.org/wiki/Tagged_union ).
Things about programming I learned with Go
131–140 of 157 posts
Re: Things about programming I learned with Go
#132Earlier quoted context omitted.
> There is no subtyping in Go. There is. Go simply has structural subtyping [1] rather than nominal subtyping. > It's interesting that you didn't bother try writing the equivalent of `let f (x: #a) = ()` in Go, because you CANNOT. You forget that OCaml also uses structural subtyping. Writing `#a` is effectively the shorthand for the inferred interface. So you can write it also as: let f (x: ) = () where is the interf…
> There is. Go simply has structural subtyping [1] rather than nominal subtyping. No there is not, period. interface { foo() int } is not sub typing. but it's interesting how you move the goal post on each comment. You go from inheritance to sub typing to "structural subtyping". You're not interested in a serious discussion.
This is an assertion, not an argument. It's not how the literature sees it. Plus, you can even have it from Rob Pike himself if you don't believe me: https://twitter.com/rob_pike/status/546973312543227904
> is not sub typing. but it's interesting how you move the goal post on each comment.
I didn't say that this piece of code constituted subtyping. Here, I was refuting your specific claim that the equivalent of `f` cannot be written in Go.
> You go from inheritance to sub typing to "structural subtyping".
This is not how the thread went. I added a reference to structural subtyping as a purely explanatory footnote to illustrate a well-known similarity between OCaml and Go; subtyping had not been mentioned at all so far. Starting at that footnote, you introduced a digression by claiming that Go does not have subtyping at all.
Re: Things about programming I learned with Go
#133Earlier quoted context omitted.
> There is. Go simply has structural subtyping [1] rather than nominal subtyping. No there is not, period. interface { foo() int } is not sub typing. but it's interesting how you move the goal post on each comment. You go from inheritance to sub typing to "structural subtyping". You're not interested in a serious discussion.
> No there is not, period. This is an assertion, not an argument. It's not how the literature sees it. Plus, you can even have it from Rob Pike himself if you don't believe me: https://twitter.com/rob_pike/status/546973312543227904 > is not sub typing. but it's interesting how you move the goal post on each comment. I didn't say that this piece of code constituted subtyping. Here, I was refuting your specific claim t…
The hell with your "assertion". Structural typing =/= structural subtyping, just like the presence of classes in a language in no way means that language supports inheritance.
> I didn't say that this piece of code constituted subtyping. I was refuting your specific claim that `f` cannot be written in Go.
It cannot since you had to add an interface to the mix, unlike with your OCaml example, which proves that go structs and OCaml classes are not similar in any way. Go structs do not support any kind of polymorphism unlike OCaml classes.
Re: Things about programming I learned with Go
#134Earlier quoted context omitted.
He speaks about non-local receivers. You can't have: func (r *otherPackage.Receiver) method(arg int)
What's the issue with composing a new type that has otherPackage.Receiver in it, and defining the new method on the new type?
Re: Things about programming I learned with Go
#135Earlier quoted context omitted.
And even with exceptions, C++ is the only mainstream language I know that has a story how to undo any investments so far, including those that are not memory allocations . In any other language, you have to at least write wrappers that execute commands and catch any exceptions to do specific cleanup actions (like aborting a database transaction). And in C++, while it has a story how to do that, implementations must i…
I don't really agree that it's inelegant to decide whether the reason for quitting is a success or an exception, or whether it's necessary. Like, you've either committed, in which case you shouldn't need to do any cleanup, or you haven't committed, in which case you need to clean up, right? If you have an object representing some sort of transaction, and you just have actually-do-all-the-work-at-once-on-commit-being-…
What we want actually executed in the end (in terms of control flow - not necessarily what we would be willing to code), is something like the following clean procedural code.
do_some_foo():
start_transaction()
r = do_thing_A()
if r == CONFLICT:
rollback()
return r
r = do_thing_B()
if r == CONFLICT:
rollback()
return r
commit()
return OKRe: Things about programming I learned with Go
#136Earlier quoted context omitted.
> Inheritance is not a way to express sum types, it's a form of subtyping. A distinction without a difference. This is probably most visible in languages like Scala and Kotlin, which implement algebraic data types by way of inheritance. That inheritance creates a subtyping relationship is irrelevant; there's a similar subtyping relationship between variants (or groups of variants) and the overarching type using a tra…
Pony ( https://ponylang.org ) uses sum types, perhaps excessively. Just yesterday, I wrote: (None | (In, USize)) I.e., None (the null valued type) or a pair made of a type variable (In) and a USize. The thing is, the values that satisfy this type are not subtypes of None and a pair. (That would be silly, given None.) Such a value is either None, or a pair.
Unless I'm misreading you, this seems to be a misunderstanding of what sum types are. A sum type `T = A | B` represents the (disjoint) union of all possible values of `A` and of all possible values of `B`, simply put, not the intersection (as you seem to indicate by the phrasing of "not subtypes of None and pair"; correct me if you meant something else).
Recall what subtyping means (I'm going with Wikipedia's definition here for sake of accessibility):
> [S]ubtyping (also subtype polymorphism or inclusion polymorphism) is a form of type polymorphism in which a subtype is a datatype that is related to another datatype (the supertype) by some notion of substitutability, meaning that program elements, typically subroutines or functions, written to operate on elements of the supertype can also operate on elements of the subtype.
This holds in the case of sum types. Operations that work on the sum type will generally also work on the variants that constitute the sum type.
The same goes for inheritance. If an abstract class T has two concrete subclasses `A` and `B`, then a value of type `T` belongs to the union of values of type `A` and of type `B`.
Re: Things about programming I learned with Go
#137Earlier quoted context omitted.
My comment mentioned mainstream languages. To my knowledge, Brainfuck is not a mainstream language used at any small, medium, or large corporation. The point about the spec was the language is small enough to master. Scheme (Lisps in general) is different because it is homoionic. Forth is not mainstream, and neither is it's paradigm. And well, I never heard of Io so I will check it out, looks neat.
And your point was refuted. Brainfuck not being mainstream is irrelevant; either a short language spec correlates with speed and easiness of mastery or it doesn't. And the counter-evidence shows that it doesn't. You can't just casually ignore inconvenient exceptions to your beliefs. I mean, you can , but it's not something that reflects positively.
Re: Things about programming I learned with Go
#138Earlier quoted context omitted.
> No there is not, period. This is an assertion, not an argument. It's not how the literature sees it. Plus, you can even have it from Rob Pike himself if you don't believe me: https://twitter.com/rob_pike/status/546973312543227904 > is not sub typing. but it's interesting how you move the goal post on each comment. I didn't say that this piece of code constituted subtyping. Here, I was refuting your specific claim t…
> This is an assertion, not an argument. It's not how the literature sees it. Plus, you can even have it from Rob Pike himself if you don't believe me: https://twitter.com/rob_pike/status/546973312543227904 The hell with your "assertion". Structural typing =/= structural subtyping, just like the presence of classes in a language in no way means that language supports inheritance. > I didn't say that this piece of cod…
Well, structural typing is used for two things, type equivalence and subtyping [1]. If it isn't subtyping, then the consequence would be that Rob Pike talked about type identity only, which doesn't make sense.
Let's pull in the definition of subtyping again:
> [S]ubtyping (also subtype polymorphism or inclusion polymorphism) is a form of type polymorphism in which a subtype is a datatype that is related to another datatype (the supertype) by some notion of substitutability, meaning that program elements, typically subroutines or functions, written to operate on elements of the supertype can also operate on elements of the subtype.
Now, one misunderstanding seems to be that you assume that I'm saying that B is or should be a subtype of A. Note that I never actually said that and it's not relevant; neither inheritance nor delegation necessarily create a subtype relationship. See "Inheritance is not subtyping" by Cook et al., a seminal paper in programming language theory [2].
Structural vs. nominative or nominal subtyping revolves around the definition of substitutability. With nominative subtyping, we have the case where a subtype relationship is constructed based on explicitly specified relationships between types identified by their names; structural subtyping exists when the type signature of the subtype conforms to the type signature of the supertype.
The latter is the case in Go. Somewhat simplified, the type of a struct (strictly speaking, of a pointer to an instance of that struct [3]) is the subtype of the type of any interface it matches.
> It cannot since you had to add an interface to the mix, unlike with your OCaml example, which proves that go structs and OCaml classes are not similar in any way.
This is because `#a` is a short-hand for "the interface of `a`". So, yes, the OCaml example does the same thing. You can reproduce it by removing the inheritance from OCaml, and it'll still work (or, without the `#`, still won't):
class a = object method foo = 0 end
class b = object method foo = 0 method bar = 1 end
let f (x: #a) = ()
let () = f (new b)
Note that the classes are completely independent; there is no inheritance at all. It's just that the interface of `b` conforms to the interface of `a`, and hence instances of `b` can be passed to functions expecting `#a`.[1] E.g. http://wiki.c2.com/?NominativeAndStructuralTyping
[2] http://dl.acm.org/citation.cfm?id=96721
[3] C++ and many other OO languages make a similar distinction, as runtime polymorphism does not work well for value types.
Re: Things about programming I learned with Go
#139Earlier quoted context omitted.
Most familiar with Python currently. Done some Ruby and Java and C and Pascal earlier. Some D and a bit of C++ and a bit of Go. I do understand that structs and tuples are examples of product types (because the range of the values for a struct or tuple is the Cartesian product of all the possible values for each field). My question was mainly about sum types as described by rbehrends, was trying to relate them in my…
Cool, so unions in C and C++ are a kind of sum type because the variable can have one of a set of types. More usually people think of tagged unions when they think of sum types, I believe Pascal's Variant Records are an example of tagged unions.
Re: Things about programming I learned with Go
#140Earlier quoted context omitted.
"but that's a misunderstanding of what inheritance is used for" I'm not sure what you imply. Most OOP languages where people tell you not to use inheritance, but composition instead, so java, c++, c#, etc. In those languages inheritance can be used to create forms of product types, but also to share and override behaviour hierarchically. They can also create sum types, and all possibility of hybrids, like weird mix o…
> I'm not sure what you imply. Most OOP languages where people tell you not to use inheritance, but composition instead, so java, c++, c#, etc. In those languages inheritance can be used to create forms of product types, but also to share and override behaviour hierarchically. They can also create sum types, and all possibility of hybrids, like weird mix of sum and product types, partially closed, etc. My point wasn'…