【问题标题】:Understanding modify function from THIH (Typing Haskell In Haskell)从 THIH 了解修改功能(在 Haskell 中键入 Haskell)
【发布时间】:2021-07-15 17:27:20
【问题描述】:
我正在阅读typing haskell in haskell
很难理解第 13 页上的这行代码
modify ce i c = ce{classes=\j→if I==j then Just c else classes ce j}
j 来自哪里?在第 13 页上有一个关于修改的简短介绍,但根本没有提到 j。
在 p14 上,调用了 addClass 下的 return(修改 ce i (is, []))。这是我想不通的地方。如果没有提供 j,如何调用修改 ce i (is, []))?感谢您的帮助。
【问题讨论】:
标签:
haskell
type-inference
【解决方案1】:
j 仍然是 lambda 表达式的一部分
\j -> if i==j then Just c else classes ce j
定义classes 字段的值。这个函数是对i、c 和ce 值的闭包,modify 本身作为参数接收。
这就像一个递归函数: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 的新值,该值包装了相同类型的“较小”值。 classes 函数一次展开该环境一层,直到找到原始参数的匹配值,或者达到 initialEnv 的值,classes initalEnv _ == Nothing。
【解决方案2】:
j 是一个 lambda 参数。您可以为参数指定任何您喜欢的名称。它代表什么? modify 的类型签名告诉我们第一个参数是 ClassEnv 类型,因此您可以阅读其定义(第 12 页)以查看其 classes 字段的类型。
【解决方案3】:
为了补充其他答案,该论文的作者所做的是仅使用函数定义一个非常简单的地图或字典。通常你可以写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
因此,不是将映射定义为值的集合,而是将映射定义为查找函数。
这种方法的一个优点是它很简单,因为它不依赖于外部依赖项。但它不是那么灵活:例如,您不能列出映射中的所有键和值;而且速度很慢:查找需要进行线性数量的相等测试。