fakedrake
fakedrake

Reputation: 6856

Typeclass instances for another typeclass in haskell

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

Answers (4)

fakedrake
fakedrake

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

user2407038
user2407038

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

Sibi
Sibi

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

leftaroundabout
leftaroundabout

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

Related Questions