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

I think the an easy way to think about it is by thinking about function types, instead of collection types.

Func Arg Val represents a function type from Args to Vals

consider foo(func : Func a b)

The argument to the function foo must be assignable to (a subtype of) Func a b

What are those subtypes? We can find out by considering expressions involving the argument

bidentifer = func(avalue)

so func must be an object whose type is compatible with assignments from the avalue, so its argument type must be a supertype of a

while the assignment to bidentifier implies the return value must be assignable to the return type so it must be a subtype

therefore the subtypes of Func a b are the set of types Func (super a) (sub b)

this is the origin of the phrase be generous in what you accept and specific about what you return

thinking about whether bikes are vehicles and such doesn't really clarify anything. you have to actually think about the expressions you are trying to construct

Moving down the Func type hierarchy moves you up the Argument type hierarchy (contra) but moves you down the Return type hierarchy (co)



> this is the origin of the phrase be generous in what you accept and specific about what you return

That definitely needs citation, as Postel's law seems to have come from TCP RFCs.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

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

Search: