Haskell模拟实例?

时间:2015-03-26 17:12:32

标签: haskell instanceof

我是Haskell的新手,所以我的问题可能很愚蠢。

我想要一个功能

show2 :: (Show a) => a -> String

对于任何show a都会返回a,但如果a本身为a则返回String。 我该如何实施呢?

P.S。如果这个功能已经在某个地方实现了,那就很棒了,但我仍然希望看到一个实现的例子。

3 个答案:

答案 0 :(得分:5)

您可以使用cast

中的Data.Typeable
show2 :: (Typeable a, Show a) => a -> String
show2 s = maybe (show s) id ms
  where ms = cast s :: Maybe String

答案 1 :(得分:4)

你可以用这段肮脏而危险的代码来做到这一点:

class Showable a where
  show2 :: a -> String

instance Showable String where
  show2 = id

instance (Show a) => Showable a where
  show2 = show

您需要-XOverlappingInstances -XFlexibleInstances -XUndecidableInstances来编译和使用它。

*Main> show2 "abc"
"abc"
*Main> show2 3
"3"

答案 2 :(得分:4)

Haskell的设计方式与instanceof检查的概念非常相反。 Haskell的设计没有包含这种运行时类型检查,因为Haskell非常注重强大的编译时保证:一个函数不应该在运行时更精确地学习它的参数类型而不是它知道它们在编译时。

这并不意味着该功能在Haskell-Lee的答案中并不存在如何实现 - 但在Haskell中这是选择加入提供的功能,而不是语言的核心部分(与Java之类的语言不同,它是一个始终存在的核心功能 - 您可以选择出来的!)。

请注意,即使在面向对象的编程中,instanceof运算符也存在争议。许多面向对象的程序员非常强烈建议不要使用它。一些例子(数百个):

所有这些中的建议往往是相同的:不是使用测试引用的类型并基于它来切换到不同的行为,而是使用多态:定义一个接口或类,它具有您想要的操作的方法,并让你使用instanceof测试的对象实现他们自己的方法版本来做正确的事情。

这个建议可以直接翻译成Haskell:

  1. 定义您自己的类型类以表示您想要的行为
  2. 为您感兴趣的每种类型实施此类型类,并为每种类型提供正确的行为。
  3. 所以,你可以这样做:

    class ToString a where
        toString :: a -> String
    
    instance ToString String where
        toString str = str
    
    instance ToString Integer where
        toString i = show i
    
    -- ...