1
votes

Is there a more concise way to write the following haskell code:

{-# LANGUAGE FlexibleInstances #-}

class Greetable g where
  hi :: g -> String

-- Here i should list all instances of Num
instance Greetable Float where
  hi s = "Hi number! " ++ show s
instance Greetable Int where
  hi s = "Hi number! " ++ show s
instance Greetable Double where
  hi s = "Hi number! " ++ show s
-- Etc.


-- Here is other stuff
instance Greetable String where
  hi s = "Hi string! " ++ s

EDIT: I would like the hi function to be able to account for any future instances of the class Num.

4

4 Answers

4
votes

There is the super-primitive way

{-# LANGUAGE CPP #-}

#define GREETABLE_NUM(n)\
instance Greetable(n) where { hi s = "Hi number! " ++ show s }

GREETABLE_NUM(Int)
GREETABLE_NUM(Double)
...

Essentially the same can be done nicer with Template Haskell, but AFAIK you'll need two modules (one for defining the macro and one for using it), which is probably overkill here.

A perhaps more sensible solution is to simply write

numberHi :: Show n => n -> String
numberHi s = "Hi number! " ++ show s

instance Greetable Int where hi = numberHi
instance Greetable Double where hi = numberHi
...
3
votes

This is a good use case for default method signatures.

{-# LANGUAGE DefaultSignatures #-}

class Greetable g where
  hi :: g -> String
  default hi :: Show g => g -> String 
  hi s = "Hi number! " ++ show s 

instance Greetable Float 
instance Greetable Int 
instance Greetable Double 
instance Greetable String where hi s = "Hi string! " ++ s
1
votes

One another way would be this:

{-#LANGUAGE ScopedTypeVariables#-}

import Data.Typeable

hi :: (Show a, Typeable a) => a -> String
hi x 
  | typeOf x == typeOf (3 :: Int) = "Hi number!" ++ show x
  | typeOf x == typeOf (3.4 :: Double) = "Hi number!" ++ show x
  | typeOf x == typeOf ("abc" :: String) = "Hi string!" ++ show x
1
votes

So all the other answers answers are pretty good and this is not "proper" Haskell with the pragmas and all but it actually does exactly what I need:

{-# LANGUAGE UndecidableInstances, FlexibleInstances #-}

class Greetable g where
  hi :: g -> String

-- Here i should list all instances of Num
instance {-# OVERLAPS #-} (Show n, Num n) => Greetable n where
  hi s = "Hi number! " ++ show s


-- Here is other stuff
instance {-# OVERLAPPABLE #-} Greetable String where
  hi s = "Hi string! " ++ s

Then in ghci:

λ> hi 1
"Hi number! 1"
λ> hi "hello"
"Hi string! hello"
λ> hi (1::Float)
"Hi number! 1.0"

For further reading see overlapping instances