Created
November 5, 2012 15:07
-
-
Save rentalcustard/4017647 to your computer and use it in GitHub Desktop.
Polymorphism => late binding
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Doer { | |
public void doStuff(Speaker speaker) { | |
speaker.speak(); | |
} | |
} | |
interface Speaker { | |
void speak(); | |
} | |
class Program { | |
public static void main(String... args) { | |
SpeakerSource someSource = new SpeakerSource(); | |
List<Speaker> speakers = someSource.getSpeakers(); | |
Doer doer = new Doer(); | |
for (Speaker speaker : speakers) { | |
doer.doStuff(speaker); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Right, I could be entirely wrong here, as I'm as confused as you are, so take this with a large pinch of salt. However, from what I understand...
One of the key features of Haskell's typeclass relationship is that the caller gets to specify the concrete type of a value. For instance
This is in contrast to the subtype relationship illustrated by Java interfaces, where the callee chooses the concrete type, and the caller depends only on the interface it requires.
So, for instance, this isn't allowed:
...this won't compile, as it's not possible for me to call (makeSpeaker (SpeakerData "Comedian" "Knock Knock!") :: Animal), and get a valid Animal instance out.
So. How then do we replicate the behaviour you're after? We can use something called an existential type:
data AnySpeaker = forall s . Speaker s => AnySpeaker s
instance Speaker AnySpeaker where
speak (AnySpeaker s) = speak s
This means that you get a value back that fulfils the contract you want (as AnySpeaker is an instance of Speaker). However, the concrete type is fully specified, which means the caller cannot then refine the type of the value. So, I guess, late binding is required for subtype polymorphism, but not for typeclass polymorphism.
More here - with a link to an article on why the existential type hack above is an antipattern
Sorry this is all a bit vague, but it's pushing the limits of my understanding too...