Haskell:如何漂亮地打印没有引号的字符串?

Ser*_*ich 6 haskell pretty-print

假设我有这种数据类型:

data SomeDataType a = SomeDataType a
Run Code Online (Sandbox Code Playgroud)

我想向用户显示它的表示(在控制台输出中),所以我需要一个“漂亮的打印”功能。我不想使用show,因为它会返回一个表达式,而我只想将我的类型的唯一字段的值转换为字符串。

我希望这种行为:

>>> let myintdata = SomeDataType (22::Int)
>>> putStrLn $ prettyPrint myintdata
22
>>> let alice = SomeDataType "Alice"
>>> let bob = SomeDataType "Bob"
>>> putStrLn $ prettyPrint alice ++ " loves " ++ prettyPrint bob
Alice loves Bob
Run Code Online (Sandbox Code Playgroud)

所以我是这样实现的:

prettyPrint :: Show a => SomeDataType a -> String
prettyPrint (SomeDataType x) = show x
Run Code Online (Sandbox Code Playgroud)

它适用于数字,但字符串被引用和转义:

>>> let alice = SomeDataType "Alice"
>>> let bob = SomeDataType "Bob"
>>> putStrLn $ prettyPrint alice ++ " loves " ++ prettyPrint bob
"Alice" loves "Bob"
Run Code Online (Sandbox Code Playgroud)

此外,我希望完全控制将来如何将不同的内容类型转换为字符串。所以,我要创建自己的类型类了!它是这样的:

{-# LANGUAGE FlexibleInstances #-}

data SomeDataType a = SomeDataType a

class PrettyPrint a where
    prettyPrint :: a -> String

instance {-# OVERLAPPABLE #-} PrettyPrint a where
    -- I don't care about this right now,
    -- let's learn how to print strings without quotes first!
    prettyPrint = const "Stupid Robot" 

instance PrettyPrint String where
    prettyPrint = id

instance Show a => PrettyPrint (SomeDataType a) where
    prettyPrint (SomeDataType x) = prettyPrint x
Run Code Online (Sandbox Code Playgroud)

我对第一次测试很满意:

>>> putStrLn $ prettyPrint "No quotes!"
No quotes!
Run Code Online (Sandbox Code Playgroud)

但是当我试图漂亮地打印我的数据类型时,不知何故正在调用一般实例而不是字符串:

>>> let alice = SomeDataType "Alice"
>>> let bob = SomeDataType "Bob"
>>> putStrLn $ prettyPrint alice ++ " loves " ++ prettyPrint bob
Stupid Robot loves Stupid Robot
Run Code Online (Sandbox Code Playgroud)

在这一点上,我怀疑有一种完全不同的方法来解决这个“漂亮的打印”问题。是这样吗?还是我的代码中遗漏了一些简单的明显错误?

max*_*kin 3

在最后一个实例中,您假设Show a编译器仅使用此信息来选择适当的实例prettyPrint x

PrettyPrint a您可以通过 require作为基类来添加更多信息:

instance PrettyPrint a => PrettyPrint (SomeDataType a) where
    prettyPrint (SomeDataType x) = prettyPrint x
Run Code Online (Sandbox Code Playgroud)