Reputation: 6856
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
.
Upvotes: 1
Views: 158
Reputation: 6856
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
Upvotes: 1
Reputation: 14598
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
Upvotes: 3
Reputation: 48766
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
Upvotes: 1
Reputation: 120751
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
...
Upvotes: 4