Initial note:
This question got closed after several edits because I lacked the proper terminology to state accurately what I was looking for. Sam Tobin-Hochstadt then posted a comment which made me recognise exactly what that was: programming languages that support intersection types for function return values.
Now that the question has been re-opened, I've decided to improve it by rewriting it in a (hopefully) more precise manner. Therefore, some answers and comments below might no longer make sense because they refer to previous edits. (Please see the question's edit history in such cases.)
Are there any popular statically & strongly typed programming languages (such as Haskell, generic Java, C#, F#, etc.) that support intersection types for function return values? If so, which, and how?
(If I'm honest, I would really love to see someone demonstrate a way how to express intersection types in a mainstream language such as C# or Java.)
I'll give a quick example of what intersection types might look like, using some pseudocode similar to C#:
interface IX { … }
interface IY { … }
interface IB { … }
class A : IX, IY { … }
class B : IX, IY, IB { … }
T fn() where T : IX, IY
{
return … ? new A()
: new B();
}
That is, the function fn
returns an instance of some type T
, of which the caller knows only that it implements interfaces IX
and IY
. (That is, unlike with generics, the caller doesn't get to choose the concrete type of T
— the function does. From this I would suppose that T
is in fact not a universal type, but an existential type.)
P.S.: I'm aware that one could simply define a interface IXY : IX, IY
and change the return type of fn
to IXY
. However, that is not really the same thing, because often you cannot bolt on an additional interface IXY
to a previously defined type A
which only implements IX
and IY
separately.
Footnote: Some resources about intersection types:
Wikipedia article for "Type system" has a subsection about intersection types.
Report by Benjamin C. Pierce (1991), "Programming With Intersection Types, Union Types, and Polymorphism"
David P. Cunningham (2005), "Intersection types in practice", which contains a case study about the Forsythe language, which is mentioned in the Wikipedia article.
A Stack Overflow question, "Union types and intersection types" which got several good answers, among them this one which gives a pseudocode example of intersection types similar to mine above.
T
defines a type, even if it's just defined within the function declaration as "some type that extends/implementsIX
andIY
". The fact that the actual return value is a special case of that (A
orB
respectively) isn't anything special here, you could just as well achieve that by usingObject
instead ofT
.T
as interfaceI
when it implements all methods of the interface, but did not declare that interface".