我正在阅读在haskell 中键入haskell的文章
很难理解p13 上的这行编码
modify ce i c = ce{classes=j→if I==j then Just c else classes ce j}
j从哪里来?在第13页上有一个关于修改的简短覆盖,但根本没有提到j。在p14上,有一个对addClass下的return(modify ce i(is,[]((的调用。这是我想不通的地方。如果没有提供j,如何调用修改ce i(is,[](?谢谢你的帮助。
j
仍然是lambda表达式的一部分
j -> if i==j then Just c else classes ce j
其定义CCD_ 2字段的值。此函数是modify
本身作为参数接收的值i
、c
和ce
的闭包。
这就像一个递归函数:modify ce i c
的结果是一个值,其中(对于某些值ce
、i
、c
和x
(
classes (modify ce i c i) == Just c
和
classes (modify ce i c x) == classes ce x`.
除了classes
实际调用自身之外,modify
创建了一个类型为ClassEnv
的新值,该值封装了一个"0";较小的";相同类型的值。classes
函数一次打开该环境一层,直到找到原始参数的匹配值,或者达到classes initalEnv _ == Nothing
所对应的initialEnv
值。
j
是lambda参数。您可以为参数指定任何您喜欢的名称。它代表什么?modify
的类型签名告诉我们第一个参数的类型是classes
0,所以您可以阅读其定义(第12页(,看看其classes
字段的类型。
为了补充其他答案,该论文的作者只使用函数定义了一个非常简单的地图或字典。通常,您可以编写Map Id Class
,其中Map
来自containers
包,但您也可以使用类型Id -> Maybe Class
,它基本上是映射类型的lookup
函数。然后可以像这样实现一些简单的功能:
type Map k v = k -> Maybe v
singleton :: Eq k => k -> v -> Map k v
singleton k v = k' -> if k == k' then Just v else Nothing
insert :: Eq k => k -> v -> Map k v -> Map k v
insert k v lookup = k' -> if k' == k then Just v else lookup k'
union :: Map k v -> Map k v -> Map k v
union lookup1 lookup2 = k -> case lookup1 k of
Nothing -> lookup2 k
v -> v
delete :: Eq k => k -> Map k v -> Map k v
delete k lookup = k' -> if k == k' then Nothing else lookup k'
lookup :: Map k v -> k -> Maybe v
lookup = id
因此,不是将映射定义为值的集合,而是将映射定义成查找函数。
这种方法的一个优点是它很简单,因为它不依赖于外部依赖关系。但它并没有那么灵活:例如,你不能列出地图中的所有键和值;而且它很慢:查找需要进行线性数量的相等性测试。