Hacker News new | past | comments | ask | show | jobs | submit login

> On the other hand, if you realise that a square is a rectangle with the same width and height, why should you bother at all with creating a new class? A new constructor (or an helper function) should be all you need

What if you have a function that only knows how to operate on squares? Forcing it to accept Rectangles will be unnatural. Of course we can use just a single type Rectangle with two constructors, but inherently that's throwing information away about certain conditions we know to be true.

Even in functional programs when we don't have inheritance, we still sometimes need conversion functions between related types and whether or not these use option types illustrates essentially the same idea:

    data Rectangle = Rectangle Int Int
    
    data Square = Square Int
    
    recToSq :: Rectangle -> Maybe Square -- may not succeed; like downcasting
    
    sqToRec :: Square -> Rectangle -- always succeeds; like upcasting
Indeed, this is exactly what the "coercion semantics" in subtyping means: whenever S is a subtype of T, we can generate a total function from S to T. I believe this is also called "inheritance as implicit coercion" in https://www.sciencedirect.com/science/article/pii/0890540191... Quoting from the abstract:

> We present a method for providing semantic interpretations for languages with a type system featuring inheritance polymorphism. […] Our goal is to interpret inheritances in Fun via coercion functions which are definable in the target of the translation.




> What if you have a function that only knows how to operate on squares? Forcing it to accept Rectangles will be unnatural

then you write another function that does what you want with rectangles. I think that most of the problems with inheritance stem from unnatural obsession for code reuse such as this.


This is a valid point, but now you have two ways of representing a square and you need the coversion functions.

It's better than nothing as you can guarantee that an instance of Square is a square, but you still need to handle squares disguised as Rectangle.

You could throw in dependent types and force rectangles to have different width and height, but that doesn't really help in getting nicer API.

If I had to do something like this in a real program I would take these issues as a sign that I need to step back and re-evaluate my design. I'd look at what I want to use these types for and try to come up with the best approach for that specific case.




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

Search: