编写富 Haskell "show" 函数的正确方法是什么?
What is the correct way to write a rich Haskell "show" function?
我对 Haskell 的 Show
和 Read
的 correct implementation 的理解是 read.show
应该是恒等式。如果为真,则 read
需要能够进行一些非常混乱的字符串解析,或者 show
必须提供相当有限的功能(从用户体验的角度来看)。
read.show == id
是这种情况吗?如果是,接受的Haskell 做法是什么——函数命名和调用——更丰富的(字符串)值表示?
首先,show
预计会生成一个遵循 Haskell 语法的字符串——理想情况下,人们应该能够将其剪切并粘贴到 Haskell 文件中,然后有那个工作。
也就是说,read . show
应该是身份。但是,有时会放宽一点,只需要
read (show x) == x
其中 (==)
是由相关 Eq
实例定义的 等效项 。
我相信这方面的典型示例是 Data.Set.Set
,它在内部表示使用平衡二叉搜索树 (BST) 的集合。它的 Show
实例生成形式为
的字符串
fromList [1,2,3,4,6,7]
read
返回这样的字符串可能会产生不同的 BST,但仍然 ==
到旧字符串。从用户的角度来看,没有(可观察到的)差异。
打印自定义 "opaque" 类型时,通常可以使用相同的 fromSomeTransparentType value
字符串编码。
最后,我想这些 Show
相关的 "social contracts" 在 libraries 中比在 applications[=45= 中更受尊重].这是因为在应用程序中,有时可以合理地假设除了应用程序本身之外没有其他人会使用这些实例。例如,我认为这对于应用程序来说还可以:
data Exp = Add Exp Exp | ...
instance Show Exp where
show (Add e1 e2) = "(" ++ show e1 ++ ", " ++ show e2 ++ ")"
"other" 法则 show . read == id
通常不成立。首先,read
是部分的。其次,即使不考虑偏向性,read
方法也可以对其输入更加宽松,例如将重复的空格视为一个空格,或忽略多余的括号:(如 AJFarmar 在下面建议的那样)
show (read "Just (((6)))") = "Just 6"
我对 Haskell 的 Show
和 Read
的 correct implementation 的理解是 read.show
应该是恒等式。如果为真,则 read
需要能够进行一些非常混乱的字符串解析,或者 show
必须提供相当有限的功能(从用户体验的角度来看)。
read.show == id
是这种情况吗?如果是,接受的Haskell 做法是什么——函数命名和调用——更丰富的(字符串)值表示?
首先,show
预计会生成一个遵循 Haskell 语法的字符串——理想情况下,人们应该能够将其剪切并粘贴到 Haskell 文件中,然后有那个工作。
也就是说,read . show
应该是身份。但是,有时会放宽一点,只需要
read (show x) == x
其中 (==)
是由相关 Eq
实例定义的 等效项 。
我相信这方面的典型示例是 Data.Set.Set
,它在内部表示使用平衡二叉搜索树 (BST) 的集合。它的 Show
实例生成形式为
fromList [1,2,3,4,6,7]
read
返回这样的字符串可能会产生不同的 BST,但仍然 ==
到旧字符串。从用户的角度来看,没有(可观察到的)差异。
打印自定义 "opaque" 类型时,通常可以使用相同的 fromSomeTransparentType value
字符串编码。
最后,我想这些 Show
相关的 "social contracts" 在 libraries 中比在 applications[=45= 中更受尊重].这是因为在应用程序中,有时可以合理地假设除了应用程序本身之外没有其他人会使用这些实例。例如,我认为这对于应用程序来说还可以:
data Exp = Add Exp Exp | ...
instance Show Exp where
show (Add e1 e2) = "(" ++ show e1 ++ ", " ++ show e2 ++ ")"
"other" 法则 show . read == id
通常不成立。首先,read
是部分的。其次,即使不考虑偏向性,read
方法也可以对其输入更加宽松,例如将重复的空格视为一个空格,或忽略多余的括号:(如 AJFarmar 在下面建议的那样)
show (read "Just (((6)))") = "Just 6"