gpt4 book ai didi

Guards 中的 Haskell 类型解构

转载 作者:行者123 更新时间:2023-12-02 00:33:57 26 4
gpt4 key购买 nike

我正在 Haskell 中玩一个玩具项目。我正在实现一些之前用其他语言构建的数据结构,以熟悉它们在 Haskell 中的构建方式。这不是我的第一个函数式语言,我已经在 OCaml 中构建了几个项目,例如方案解释器,但我认为我的 OCaml 经验影响了我解决这个问题的方式。知道我正在实现的数据结构是 PR-四叉树,这并不是非常重要,但对于上下文可能有用。

我想要做的是匹配并解构守卫内的类型,即 OCaml 的匹配语句。

data Waypoint = WayPoint {
lat :: Float,
lon :: Float,
radius :: Float,
speed :: Float,
accel :: Float
} deriving (Show)

data Region = Region {
x :: Float,
y :: Float,
width :: Float
} deriving (Show)

data PRQuadtree = WhiteNode Region
| BlackNode Region Waypoint
| GreyNode {
topLeft :: PRQuadtree,
topRight :: PRQuadtree,
botLeft :: PRQuadtree,
botRight :: PRQuadtree,
region :: Region
} deriving (Show)

getRegion node
| BlackNode(r, _) = r
| WhiteNode(r) = r
| GreyNode = region node

getRegion 函数是我特别遇到问题的函数。如果我想要做的事情不清楚:我想简单地提取参数的一个元素,但这取决于参数是代数数据类型的哪个成员。在 OCaml 中我可以这样做:

let getRegion node = match node with
| BlackNode(r, _) = r
| WhiteNode(r) = r
| GreyNode = region(node)

(或者非常类似的东西,我的 OCaml 现在有点生疏了)。

然而,在 Haskell 中,这似乎并未将 r 绑定(bind)到保护分支的 RHS 范围内。我尝试查找模式守卫,因为它们听起来与我想要做的类似,但我无法真正理解这里发生的事情。实际上,我只想获得从 = 的 LHS 到 equals 的 RHS 的绑定(bind)(取决于我们已经下降的守卫的哪个分支)。

完成我在这里想做的事情的惯用 Haskell 方法是什么?

最佳答案

可以通过如下方式实现:

getRegion :: PRQuadtree -> Region
getRegion (BlackNode r _) = r
getRegion (WhiteNode r) = r
getRegion GreyNode{region=r} = r

或者甚至是

getRegion :: PRQuadtree -> Region
getRegion x = case x of
BlackNode r _ -> r
WhiteNode r -> r
GreyNode{} -> region x

在 Haskell 中,在前面添加类型签名是非常惯用的。

另一个选项是将 region 字段也扩展到其他情况:

data PRQuadtree = WhiteNode { region :: Region }
| BlackNode { region :: Region , waypoint :: Waypoint }
| GreyNode {
topLeft :: PRQuadtree,
topRight :: PRQuadtree,
botLeft :: PRQuadtree,
botRight :: PRQuadtree,
region :: Region
} deriving (Show)

现在,region 将适用于所有 PRQuadtree 值。

Haskell 像 ML 在定义代数数据类型时那样使用 | 来分隔不同的构造函数,但不使用它来分隔 case 分支,而是遵循语法

case .. of { pat1 -> e1 ; pat2 -> e2 ; ... }

可以用缩进代替

case .. of
pat1 -> e1
pat2 -> e2
...

另请注意,不鼓励使用部分字段选择器:

data A = A1 { foo :: Int } | A2

上面,foo A2 类型检查但崩溃了。另一方面,当所有构造函数中都存在某个字段时,我们就不会面临这样的风险。

关于Guards 中的 Haskell 类型解构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34685523/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com