2016-01-06 62 views
4

假設我有這樣的數據類型:哈斯克爾:如何漂亮的打印不帶引號的字符串?

data SomeDataType a = SomeDataType a 

我想表明其對用戶(在控制檯輸出)表示,所以我需要一個「漂亮打印」功能。我不想使用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 

所以我實現它是這樣的:

prettyPrint :: Show a => SomeDataType a -> String 
prettyPrint (SomeDataType x) = show x 

它的做工精細的數字,但字符串越來越引用和轉義:

>>> let alice = SomeDataType "Alice" 
>>> let bob = SomeDataType "Bob" 
>>> putStrLn $ prettyPrint alice ++ " loves " ++ prettyPrint bob 
"Alice" loves "Bob" 

另外,我想完全控制將來如何將不同的內容類型轉換爲字符串。所以,我要創建我自己的類型類別!它是這樣的:

{-# 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 

我很高興第一次測試:

>>> putStrLn $ prettyPrint "No quotes!" 
No quotes! 

但是,當我試圖漂亮打印我的數據類型,不知何故一般情況下被調用,而不是字符串的:

>>> let alice = SomeDataType "Alice" 
>>> let bob = SomeDataType "Bob" 
>>> putStrLn $ prettyPrint alice ++ " loves " ++ prettyPrint bob 
Stupid Robot loves Stupid Robot 

在這一點上,我懷疑有一種完全不同的方法來解決這個「漂亮的打印」問題。是這樣嗎?或者我在代碼中遺漏了一些簡單明顯的錯誤?

回答

3

在最後一個例子中,假設Show a和編譯器僅使用此信息爲prettyPrint x選擇適當的實例。

您可以通過要求PrettyPrint a作爲基類添加更多的信息:

instance PrettyPrint a => PrettyPrint (SomeDataType a) where 
    prettyPrint (SomeDataType x) = prettyPrint x