Haskell instanceof 模拟?

Haskell instanceof analogue?

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

我想要一个函数

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

对于任何 a,这将 return show a,但如果 a 本身是 String,则 a。 我该如何实施?

P.S。如果这个功能已经在某个地方实现了,那就太好了,但我还是想看一个实现的例子。

您可以使用 Data.Typeable

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

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

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"

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

这并不意味着该功能在 Haskell 中不存在——Lee 的回答演示了如何做到这一点——但在 Haskell 中,这是一个 opt-in 提供的特性,不是语言的核心部分(不像 Java 这样的语言,它是始终存在的核心特性——你可以'选择退出!)。

请注意,即使在面向对象编程中,instanceof 运算符也是有争议的。许多面向对象的程序员强烈反对使用它。几个例子(数百个):

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

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

  1. 定义你自己的类型class来代表你想要的行为
  2. 为您感兴趣的每种类型实施此类型 class,并为每种类型实现正确的行为。

所以,你可以这样做:

class ToString a where
    toString :: a -> String

instance ToString String where
    toString str = str

instance ToString Integer where
    toString i = show i

-- ...