我对Haskell的Show
和Read
的correct implementation的理解是,read.show
应该是身份。如果为true,则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,但仍然比旧字符串更==
。从用户的角度来看,没有(可观察到的)差异。打印自定义“不透明”类型时,通常可以使用相同的
fromSomeTransparentType value
字符串编码。最后,我想这些
Show
相关的“社会契约”在图书馆中比在应用程序中受到更多的尊重。这是因为在应用程序中,有时人们可以合理地假设,除了应用程序本身之外,没有人会使用这些实例。例如,我认为这对于应用程序来说还可以:data Exp = Add Exp Exp | ...
instance Show Exp where
show (Add e1 e2) = "(" ++ show e1 ++ ", " ++ show e2 ++ ")"
通常,“其他”法律
show . read == id
不成立。首先,read
是不完整的。其次,即使不考虑局部性,也允许read
方法对其输入更为宽大,例如将重复的空格视为一个空格,或忽略多余的括号:(如AJFarmar所建议的那样)show (read "Just (((6)))") = "Just 6"