3 ms·
Type-classes are like interfaces, but not quite the same. They allow return-type polymorphism, which ordinary OO interfaces do not. And the Monad type-class re
by Peaker 15y ago
Type-classes are like interfaces, but not quite the same.
They allow return-type polymorphism, which ordinary OO interfaces do not. And the Monad type-class requires this feature.
Basically, when you call the "return" function in Haskell, (e.g: return 5) -- the code being called depends on the type of the result. The type of the result is determined from the context (by type-inference or rarely, type annotations). In Ruby or Python, there's no easy/direct way to encode something like "return" such that it works with any Monad instance.
- jeffdavis 15y agoInteresting. I see what you are saying, but could you provide an example (or a link to an example) for clarity? Preferably something not easily accomplished in ruby?
- eru 15y agoI found an article about return-type polymorphism. See http://vpatryshev.blogspot.com/2010/01/dispatch-by-return-type-haskell-vs-java.html http://vpatryshev.blogspot.com/2010/01/dispatch-by-return-ty... One thing is impossible, though: defining two methods that differ only in return type, something like Most important point: Something like int i = parse(String source); long l = parse(String source); boolean b = parse(String source); is possible in Haskell, but not in Python, and barely imaginable in Java.
- Peaker 15y agoElaboration: class Read r where read :: String -> Maybe r Note that it's polymorphic on the type of the return within the Maybe. It's very flexible, the polymorphic type can appear anywhere within the type signature. Now you can write various functions that use "read" and they all remain return-type polymorphic. For example, you can write one that loops, requesting the user to repeat entry until parse-able data (of the wanted type) is given: repeatReadingUntilValid :: Read r => IO r repeatReadingUntilValid = do line <- getLine case read line of Nothing -> do putStrLn $ "Invalid input: " ++ show line repeatReadingUntilValid Just result -> return result That's just a silly example, because read isn't that interesting. Another example is QuickCheck, which uses type-classes to auto-generate fuzz-testers for functions. For example: import Test.QuickCheck pretty :: MyType -> String pretty = .. pretty print my type here .. unpretty :: String -> MyType unpretty = .. parse the pretty printing of my type here .. Now I can test that unpretty is indeed the inverse of pretty: quickCheck (\x -> unpretty (pretty x) == x) (for every x, the unpretty of pretty of x equals x). I can generalize this property to: isInverse f g x = f (g x) == x And then use: quickCheck (isInverse unpretty pretty) Similarly you can define: commutative f x y = x `f` y == y `f` x associative f x y z = (x `f` y) `f` z == x `f` (y `f` z) transitive f x y z = x `f` y && y `f` z ==> x `f` z Which makes an important type of unit testing a breeze. The type system is saving us from writing code here.