【问题标题】:Typeclass instances for another typeclass in haskellhaskell 中另一个类型类的类型类实例
【发布时间】:2015-09-07 22:53:47
【问题描述】:

有没有更简洁的方式来编写下面的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 类的任何未来实例。

【问题讨论】:

    标签: haskell typeclass


    【解决方案1】:

    所以所有其他答案的答案都很好,这不是“正确”的 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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 这很不错,但关键是还要考虑Num 的未来实例,例如,如果它也是Show 的实例,我们希望以数字instance Num Matrix .... 表示欢迎。
      【解决方案3】:

      另一种方式是这样的:

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

      【讨论】:

        【解决方案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
        ...
        

        【讨论】:

          猜你喜欢
          • 2016-08-12
          • 1970-01-01
          • 1970-01-01
          • 2018-11-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多