当它是String时使用“id”,否则使用“show”

时间:2015-11-19 00:19:01

标签: haskell

我有以下代码

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

有可能吗?任何解决方法?

2 个答案:

答案 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