假设您声明了两个同构
showing :: (Read a, Show a) => Iso' String a
showing = iso read show
reading :: (Read a, Show a) => Iso' a String
reading = iso show read
它们不安全,并非每个String都会解析为a。
这引出了一个问题:如果enum = iso fromEnum toEnum
是,那么为什么这两个人不会被包含在库中?
它同样不安全,不能被类型系统阻止。他们都把负担转嫁给程序员,程序员必须确保转换不会破坏同构。
快速示例:under enum (+1) True
将抛出异常
答案 0 :(得分:6)
警告:随后是推测性答案。
我能想到的两个场景之间的一个区别是,当toEnum
出现故障时,可以相当容易地澄清(引用the lens docs:"这只是来自数值范围的同构实际使用"),而read
涉及的事情有点模糊。另一个区别是toEnum
是Enum
的方法(在最小实例定义中需要一个方法),而read
实际上不是{{1}的方法在某种意义上,从某种意义上讲,它不那么重要(事实上, base docs explicitly discourage its usage)。
更一般地说,当涉及在暴露防弹界面和包括有用但可能不安全或非法的组合器之间进行选择时,镜头通常适用于后者,使它们适用于那些谁愿意使用它们同时承认文档中的任何潜在问题(或者,在更多的情况下,在函数和模块名称中)。鉴于镜头是一个非常通用的库,这种方法可以被视为一种非自以为是的选择 - 在这样的上下文中,很难弥补组合器的缺失。
P.S。:值得注意的是,镜头对Read
和read
至the _Show
prism进行编码。 show
相当于_Show
,并且对于prism' show readMaybe
值的偏倚是安全的。
答案 1 :(得分:1)
除了其他答案中的优秀评论外,我对这些定义的合法性犹豫不决。对于定义的标准实例,fromEnum . toEnum
(反之亦然)实际上是id
。但show . read
不是,即使对于完全定义的值并且仅使用标准实例,因为它规范化格式化和括号:
> show (read "(5)" :: Int)
"5"
Data.Tree> show (read "Node { rootLabel=3 ,subForest=[]}" :: Tree Int)
"Node {rootLabel = 3, subForest = []}"