Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> The Rectangle > Square problem does not happen because the programmer is not able to specify the necessary type constraints, but because she chooses not to.

The rectangle-square problem arises because there's no such thing as a type of rectangles in Go to begin with. Rectangles are mathematical objects, and mathematical objects don't mutate or have a physical identity in computer memory. If you change the width or the height of a rectangle, what you get is a different rectangle.

> The problem is not the types. The errors you get when you violate LSP are not type errors, but logic errors.

Types and logic are two different ways to look at essentially the same thing: https://existentialtype.wordpress.com/2011/03/27/the-holy-tr...



The rectangle-square problem arises because there's no such thing as a type of rectangles in Go to begin with.

You are aware that Go and a lot of other languages allow the programmer to create new types, right?

Rectangles are mathematical objects, and mathematical objects don't mutate or have a physical identity in computer memory

Well, I would quibble with your assertion as to what mathematical objective do and don't do. Mathematical objects – like computer models – have whichever properties we assign to them, if that makes them useful. I agree that immutability is one way to ensure that LSP is not violated. And I also agree that a Rectangle is probably best modeled as an immutable value object. But LSP doesn't actually talk about Rectangles and Squares, that just happens to be the example everyone always uses to illustrate it.

Types and logic are two different ways to look at essentially the same thing

Perhaps I should have used the term modeling error instead. My point was that types can't save you from modeling the domain wrongly. The type system can't save you from using Floating Point numbers to model money for instance.


> You are aware that Go and a lot of other languages allow the programmer to create new types, right?

Yes. But they don't let you create a type whose inhabitants are rectangles: https://news.ycombinator.com/item?id=12233268

> Mathematical objects – like computer models – have whichever properties we assign to them, if that makes them useful.

Sure. You can invent your own mathematical object that's kinda like a rectangle, but can mutate. As long as you don't call it “rectangle”, there will be no confusion.

> I agree that immutability is one way to ensure that LSP is not violated.

Immutability isn't enough to solve the rectangle-square problem. For instance, Standard ML has immutable values (as well as mutable objects), but it doesn't solve the problem because the core language doesn't have subtypes to begin with. Solving the problem requires refinement types, so that squares can be defined as a refinement over rectangles.

And the LSP is never violated, because it's a tautology. It just buys you less than you think in most languages.

> And I also agree that a Rectangle is probably best modeled as an immutable value object.

The notion of a “value object” is still problematic. A “value object” still has a physical identity in computer memory. What you need to do is ditch the object and work with the value itself.

> My point was that types can't save you from modeling the domain wrongly. The type system can't save you from using Floating Point numbers to model money for instance.

Of course. But I never said that types automatically make your models correct. What I said is that you need appropriate type structure to model your problem domain correctly. It's a necessary but not sufficient condition.


Yes. But they don't let you create a type whose inhabitants are rectangles.

I have no idea you mean by that. The link you provided did not help.

Immutability isn't enough.

I'm sceptical about that. I am going to need an example of a LSP violations made with immutable types.

For instance, Standard ML has immutable values (as well as mutable objects), but it doesn't solve the rectangle-square problem because the core language doesn't have subtypes to begin with. Solving the problem requires refinement types, so that squares can be defined as a refinement over rectangles.

I'm not sure what you are saying here. Does ML prevent the problem, or doesn't it? You seem to be saying that it doesn't. But according to Wikipedia, ML is type safe (for some definition of that term), and in your initial comment, you stated that type safe languages ensure adherence to LSP.

The notion of a “value object” is still problematic. A “value object” still has a physical identity in computer memory.

Because I can get the address of it in Go? So what? That's hardly something you do by accident. And if your point is about what the language makes possible, rather than what it makes likely, I assure you that you can get in wrong in any language. The only difference is how much effort it requires.

I never said that types automatically make your models correct

You pretty much did with your initial comment that type safe languages prevent violations of LSP.

you need appropriate type structure to model your problem domain correctly

No, simply not true. You can model your domain correctly in any Turing-complete language. Types may make it easier, especially as your programs grow more complex, but types can't help you choose the correct way to model your domain.

LSP is not about type errors: The symptoms of violating it are not that operations are performed on values that are not appropriate for values of that type. In the Rectangle/Square example, calling setWidth() or setHeight() on a Square are perfectly alright as far as the Type system is concerned. The problem is simply that the resulting behaviour of the program probably not what the programmer intended. If the programmer had thought to specify -- using types -- that a Rectangle’s width and height should always be independently adjustable, then it's probably a fair assumptions that the same programmer would not have accidentally made a subtype of Rectangle that violated this invariant to begin with.


> I have no idea you mean by that. The link you provided did not help.

You can't define a type in Go whose instances are rectangles. If you define:

    type Rectangle struct {
        Width, Height int
    }
Then a so-called “Rectangle” is actually a mutable object whose current state is one rectangle, but whose state the very next moment might be another rectangle.

> I'm sceptical about that. I am going to need an example of a LSP violations made with immutable types.

I never said that ML violates the LSP. I said that it doesn't solve the rectangle-square problem.

> I'm not sure what you are saying here. Does ML prevent the problem, or doesn't it? You seem to be saying that it doesn't. But according to Wikipedia, ML is type safe (for some definition of that term), and in your initial comment, you stated that type safe languages ensure adherence to LSP.

ML adheres to the LSP trivially, because the language has no subtyping relation to begin with. Another way to view this is that every type has exactly one subtype: the type itself. Unfortunately, precisely because of this, it doesn't solve the rectangle-square problem.

> Because I can get the address of it in Go? So what? That's hardly something you do by accident. And if your point is about what the language makes possible, rather than what it makes likely,

I can't prove theorems about what a language makes “likely”.

> I assure you that you can get in wrong in any language. The only difference is how much effort it requires.

You can't take the address of a rectangle in ML. The only things that have physical identities are reference cells, and two physically distinct reference cells are always considered different values, even if their contents are the same.

> In the Rectangle/Square example, calling setWidth() or setHeight() on a Square are perfectly alright as far as the Type system is concerned.

What you're calling a “Square” is, as a matter of fact, not a square.

> LSP is not about type errors: The symptoms of violating it are not that operations are performed on values that are not appropriate for values of that type.

You are projecting your wants and desires (namely: a type of rectangles, a type of squares, and that the latter be a subtype of the former) onto the LSP, but the LSP doesn't care. The LSP only cares about the types the language actually gives you. The meaning of a type isn't in its name, but in what its instances actually do.

> If the programmer had thought to specify -- using types -- that a Rectangle’s width and height should always be independently adjustable,

Then the programmer doesn't know what a rectangle is. (Assuming you meant “adjustable using a setter”.)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: