1

Is pattern matching not allowed for types to be matched as in the following example?

printit :: Int -> IO ()
printit i = print $ "Int i = " ++ show i

printit :: [Char] -> IO ()
printit s = print $ "[char] s = " ++ show s

main :: IO ()
main = do
    printit 2
    printit "two"
AJF
  • 11,767
  • 2
  • 37
  • 64
Cap
  • 99
  • 2
  • 11

1 Answers1

2

Type classes provide something similar to that:

class Printable a where printit :: a -> IO ()
instance Printable Int    where printit i = print $ "Int i = "    ++ show i
instance Printable [Char] where printit s = print $ "[char] s = " ++ show s

You probably want putStrLn instead of print in both implementations. You may also like the Typeable class; one could write

printWithType :: (Show a, Typeable a) => a -> IO ()
printWithType v = putStrLn $ show v ++ " :: " ++ show (typeOf v)

...which behaves thus:

> printWithType 3
3 :: Integer
> printWithType "foo"
"foo" :: [Char]
Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380
  • Note: `[char] s =` is incorrect, it's really `char s =`. Implementing a `Printable` instance for lists, or at least for `[Char]`, [would be tricky](http://stackoverflow.com/questions/5941701/why-can-i-not-make-string-an-instance-of-a-typeclass), I suppose. – 9000 Jul 17 '15 at 20:25
  • @9000 Oh, whoops, thanks for pointing that out! Should be fixed now. It's not tricky, though this approach does require the `FlexibleInstances` extension. There are more complicated approaches that avoid extensions; e.g. see `showList` and its history for the core idea. – Daniel Wagner Jul 17 '15 at 20:26
  • Well, yes. Just printing lists is perfectly doable. I wonder if it is possible at all to make a `Printable` that prints `"[foo] = ..."` if called with an argument of type `[foo]`, without just defining an instance for every supported case (via `FlexibleInstances`). – 9000 Jul 17 '15 at 20:35
  • @9000 It is possible, yes, and even fairly easy. For example, my one-line `printWithType` function does it. You can replicate and specialize the core ideas of `printWithType` to make a leaner typeclass than `Typeable`, but the basic idea is the same. – Daniel Wagner Jul 17 '15 at 20:39
  • @9000 Perhaps the key insight you're missing is that one can write something like `instance Foo a => Foo [a]` to handle all types of lists in one go (provided the element types implement some type class). I'm not too sure, though; maybe you would like to open a fresh question with the details of what you're wondering? – Daniel Wagner Jul 17 '15 at 20:40
  • After working/thinking for years with imperative programming models changing to functional will take a lot of practice and effort. Help from others as here and others eases this. For now these responses are sufficient for me. Thanks! – Cap Jul 28 '15 at 10:07