我是Haskell的新手,所以我的问题可能很愚蠢。
我想要一个功能
show2 :: (Show a) => a -> String
对于任何show a
都会返回a
,但如果a本身为a
则返回String
。
我该如何实施呢?
P.S。如果这个功能已经在某个地方实现了,那就很棒了,但我仍然希望看到一个实现的例子。
答案 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:
所以,你可以这样做:
class ToString a where
toString :: a -> String
instance ToString String where
toString str = str
instance ToString Integer where
toString i = show i
-- ...