Search code examples
if-statementhaskelltypespolymorphism

Haskell - types and if statements


Is there a good way to use type information to choose to do different things?

For example, this isn't valid Haskell, but I don't see why it couldn't be:

tostring :: (Show b) => b -> String
tostring x = f x where f = if b == String then tail . init . show else show

The important part is not getting the correct string out, but using the type of b as a way to switch between functionality/functions.


Solution

  • @chi's answer already demonstrates how to use Typeable to do run-time type checking, but I'd like to point out that to me, this looks like exactly the thing typeclasses are meant for. For your example, the only problem is that you don't like the Show implementation for String: In that case, just create your own typeclass!

    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE UndecidableInstances #-}
    
    -- The class
    class MyShow a where
        myShow :: a -> String
    
    -- The instance for String
    -- (The `OVERLAPPING` pragma is required, because
    -- otherwise GHC won't know which instance to choose for String)
    instance {-# OVERLAPPING #-} MyShow [Char] where
        myShow = tail . init . show
    
    -- For everything that is not a String, just copy the Show instance
    instance Show a => MyShow a where
        myShow = show
    

    EDIT: As pointed out by leftaroundabout, overlapping instances are complicated and can lead to some unexpected behavior. Look at the example at the bottom of the documentation.