我有以下代码
data Showable = forall a . (Show a) => Showable a
instance Show Showable where
show (Showable a) =
show a
它运作得很好:
> show (Showable 1)
"1"
> show (Showable True)
"True"
但是当它是一个字符串时,我会收到不需要的引号:
> show (Showable "foo")
"\"foo\""
我知道这是因为将show
应用于字符串,所以它与:
> show "foo"
"\"foo\""
我想做的是,当它是String
时,请使用id
代替show
。
类似的东西:
instance Show Showable where
show (Showable a) =
case a of
(String _) -> id a
_ -> show a
有可能吗?任何解决方法?
答案 0 :(得分:1)
有可能沿着这些方向做一些事情,但不幸的是你需要一些样板,所以最好以不同的方式去做。
这是一种可以做到的方法(使用等同于dependent sum的东西):
{-# LANGUAGE ExistentialQuantification, GADTs, DataKinds, TypeFamilies #-}
type family StringP a where
StringP String = 'True
StringP a = 'False
data CheckStringness a where
IsTypeString :: CheckStringness String
NotTypeString :: (StringP a) ~ 'False => CheckStringness a
data Showable = forall a. Show a => Showable (CheckStringness a) a
instance Show Showable where
show (Showable IsTypeString str ) = str
show (Showable NotTypeString other) = show other
困难的部分是你不能以你想要的方式直接将一个类型反映到一个值中,所以你必须编写一些样板代码来处理它。
使用示例:
ghci> show (Showable NotTypeString (123 :: Int))
"123"
ghci> show (Showable NotTypeString ())
"()"
ghci> show (Showable IsTypeString "abc")
"abc"
就像我说的那样,我会尝试以完全不同的方式解决问题(比如Luis Casillas&ErikR在这个问题的评论中提出的建议),以避免陷入这种情况在这第一位。我证明这一点的主要原因是类似于这种技术的东西在某些方面可能会变得更好,并且比现在具有更多的实用价值,特别是随着依赖的Haskell计划的继续。
答案 1 :(得分:0)
我不知道该怎么做,但我很确定这需要一些Haskell扩展。首先,存在等式约束,如(a ~ String)
。本文解释了~
表示法:http://chrisdone.com/posts/haskell-constraint-trick
此外,还有重叠的实例:https://wiki.haskell.org/GHC/AdvancedOverlap
这是我要做的(未经测试的代码,不太可能编译):
class Show1 a where
show1 :: a -> String
-- requires some extension since String = [Char]
instance (a ~ String) => Show1 a where
show1 = id
instance Show a => Show1 a where
show1 a = show a
instance Show Showable where
show (Showable a) = show1 a