haskell中另一个类型类的Typeclass实例

时间:2015-06-22 13:06:59

标签: haskell typeclass

是否有更简洁的方法来编写以下haskell代码:

{-# 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

编辑:我希望hi函数能够解释班级Num的任何未来实例。

4 个答案:

答案 0 :(得分:4)

有超原始的方式

{-# LANGUAGE CPP #-}

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

GREETABLE_NUM(Int)
GREETABLE_NUM(Double)
...

使用Template Haskell基本上可以做得更好,但是AFAIK你需要两个模块(一个用于定义宏,一个用于使用它),这在这里可能有些过分。

一个更明智的解决方案就是简单地写

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

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

答案 1 :(得分:3)

这是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

答案 2 :(得分:1)

另一种方式是:

{-#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

答案 3 :(得分:1)

因此所有其他答案的答案都非常好,而且这不是"正确的"带有pragma的Haskell以及它实际上完全符合我需要的所有内容:

{-# 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

然后在ghci:

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

如需进一步阅读,请参阅overlapping instances