gpt4 book ai didi

haskell - Haskell中where子句的执行

转载 作者:行者123 更新时间:2023-12-05 02:03:13 25 4
gpt4 key购买 nike

我得到了以下我知道有效的代码片段,但我对 Haskell 完全陌生并且有 2 个关于 where 子句的问题。

f3 :: [[Int]] -> [Int] -> [Int]
f3 [] status = status --- Base Case
f3 ([p1,p2]:tail) status
| status !! (p1-1) == 0 = f3 tail status --- Case 1
| status !! (p2-1) == 1 = f3 tail newStatus1 --- Case 2
| otherwise = f3 tail newStatus2 --- Case 3
where newStatus1 = set status p1 0 --- Line 7
newStatus2 = set newStatus2Temp p1 1 --- Line 8
newStatus2Temp = set status p2 0 --- Line 9

所以基本上 f3 谓词有 2 个参数:

  • 整数列表的列表,如下所示:[[1,2],[2,3],[3,2]]
  • 一个整数列表

它的输出是最后更新的第二个参数。

如您所见,除了基本情况外,我还有 2 种情况 (2) 和 (3),其中 status/[Int] 参数通过标准集合谓词

问题 1):

  • 假设情况 2 为真。 Haskell 是否执行第 8 行和第 9 行?
  • 假设情况 3 成立。 Haskell 是否执行第 7 行?

问题2):

  • 守卫可以有自己的位置吗?
  • 有没有更好的方法来实际做到这一点?

最佳答案

作为惰性评估的结果,第 7-9 行中的每一行中的代码仅在相应绑定(bind)的值在匹配案例的代码评估过程中被评估/使用时才会运行。所以:

  • 如果情况 1 为真,则第 7-9 行都不会运行。
  • 如果情况 1 为假但情况 2 为真,则 newStatus 的计算将运行第 7 行,但不会运行第 8-9 行。
  • 如果情况 1 和情况 2 为假但情况 3 为真,则 newStatus2 的评估运行第 8 行,该行评估 newStatus2Temp 导致第 9 行运行。第 7 行未运行。

where 子句本身只能附加到整个模式绑定(bind)(例如,整个 f3 ([p1,p2]:tail) status | ... | ... = ... 表达式),而不是单个守卫,因此守卫不能有自己的 where 子句。您可以为每个守卫重复该模式:

f3 :: [[Int]] -> [Int] -> [Int]
f3 [] status = status
f3 ([p1,p2]:tail) status | status !! (p1-1) == 0 = f3 tail status
f3 ([p1,p2]:tail) status | status !! (p2-1) == 1 = f3 tail newStatus1
where newStatus1 = set status p1 0
f3 ([p1,p2]:tail) status | otherwise = f3 tail newStatus2
where newStatus2 = set newStatus2Temp p1 1
newStatus2Temp = set status p2 0

或使用 let ... in ... block :

f3 :: [[Int]] -> [Int] -> [Int]
f3 [] status = status
f3 ([p1,p2]:tail) status
| status !! (p1-1) == 0 = f3 tail status
| status !! (p2-1) == 1
= let newStatus1 = set status p1 0
in f3 tail newStatus1
| otherwise
= let newStatus2 = set newStatus2Temp p1 1
newStatus2Temp = set status p2 0
in f3 tail newStatus2

我认为您的 where 子句版本没有任何问题,而且编写 Haskell 代码也很常见,其中只有 where 中绑定(bind)的子集-clause 用于每种情况(甚至有效/有意义)。有了这么小的助手,这个具体的例子在没有任何助手的情况下可能会写得更清楚:

f3 :: [[Int]] -> [Int] -> [Int]
f3 [] status = status
f3 ([p1,p2]:tail) status
| status !! (p1-1) == 0 = f3 tail $ status
| status !! (p2-1) == 1 = f3 tail $ set status p1 0
| otherwise = f3 tail $ set (set status p2 0) p1 1

使用 GHC 和 -O2,所有这四种代码(您的原始代码和这三种变体)都可以编译成相同的低级代码,因此请使用您认为最清晰的代码。

关于haskell - Haskell中where子句的执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65400372/

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