Haskell中的show函数似乎没有做它应该做的事情:
Prelude> let str = "stack\n\noverflow"
Prelude> putStrLn str
stack
overflow
Prelude> show str
"\"Stack\\n\\n\\noverflow\""
Prelude>
Run Code Online (Sandbox Code Playgroud)
当我声明函数时,我通常将类型签名设置为Show,它不能正确处理换行符.我希望它\n作为换行符,而不是字面意思"\n".当我将类型更改为String时,函数可以正常工作.但是我必须为整数,浮点数等实现一个单独的函数.
例如,我可以声明一个函数:
foo :: (Show x) => x -> IO ()
foo x = do
putStrLn $ show x
Run Code Online (Sandbox Code Playgroud)
......并以这种方式称呼它:
foo "stack\n\noverflow"
foo 6
foo [1..]
Run Code Online (Sandbox Code Playgroud)
如何让函数返回预期的函数?即哪个函数类似show但可以返回包含换行符的字符串?
在我熟悉的大多数OO语言中,a的toString方法String实际上只是身份函数.但在Haskell中show添加了双引号.
所以如果我写一个像这样的函数
f :: Show a => [a] -> String
f = concat . map show
Run Code Online (Sandbox Code Playgroud)
它按预期的数字工作
f [0,1,2,3] -- "0123"
Run Code Online (Sandbox Code Playgroud)
但字符串最终会有额外的引号
f ["one", "two", "three"] -- "\"one\"\"two\"\"three\""
Run Code Online (Sandbox Code Playgroud)
当我真的想要的时候"onetwothree".
如果我想以f多态方式编写,是否有办法只使用Show约束,而不覆盖Show的String实例(如果可能的话).
我能想到的最好的方法是创建自己的类型类:
class (Show a) => ToString a where
toString = show
Run Code Online (Sandbox Code Playgroud)
并为一切添加实例?
instance ToString String where toString = id
instance ToString Char where toString = pure
instance ToString Int
instance ToString Maybe
...etc
Run Code Online (Sandbox Code Playgroud)