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

Elaboration:

  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.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: