gpt4 book ai didi

haskell - 在haskell中无需递归即可进入范围

转载 作者:行者123 更新时间:2023-12-02 10:48:28 26 4
gpt4 key购买 nike

我正在学习 Haskell,但遇到了这个问题。我正在创建一个名为 getInRange 的函数,它接受两个整数和一个列表作为参数 v1、v2 和 iL 。基本上我想遍历列表 iL,并获取 v1 和 v2 范围内的数字。我正在尝试使用高阶函数来解决这个问题,所以没有递归。我对柯里化(Currying)也很陌生,并尝试在我的解决方案中使用它。我有一个辅助函数“检查”,它会检查给定值 x 是否在 v1 和 v2 的范围内。我尝试运行我的代码,但最终收到 error: parse error on input 'getInRange' 这是我的代码:

check v1 v2 z  = if (z > v1 && z < v2) then z

--getInRange
getInRange :: Ord a => a -> a-> [a] -> [a]
getInRange v1 v2 (x:xs) = foldr (check v1 v2) [] (x:xs)

作为输入和输出的示例,

getInrange 3 5 [1,2,3,4,5,6,7] 
= [4]

最佳答案

您收到语法错误,因为 if 没有 else。在 Haskell 中,这始终是强制性的。

从列表中过滤元素的正常方法是 filter 函数,因此我的答案的其余部分将被拆分:使用 filter 的一个(这是惯用的) ,以及使用 foldr 的一个,尽管这并不常见(如果您想这样做,无论是为了学习还是只是为了好玩)。

过滤器

由于 filter 采用 a -> Bool 类型的过滤函数,并且您的条件返回 Bool,因此您不需要if 根本没有,所以将您的 check 函数更改为:

check v1 v2 z  = z > v1 && z < v2

然后更改您的 getInRange 函数以使用 filter:

getInRange :: Ord a => a -> a-> [a] -> [a]
getInRange v1 v2 = filter (check v1 v2) -- see below about your (x:xs)

文件夹

要使用foldr,您需要一个a -> b -> b类型的折叠函数,其中a是列表元素,b 是结果的类型。在本例中,结果为 Ord a => a -> [a] -> [a]。为了使 check 工作,如果条件为真,则需要将元素附加到正在构建的结果中,如果条件不为真,则保留结果:

check v1 v2 z acc  = if (z > v1 && z < v2) then z:acc else acc

或者,清理一下:

check v1 v2 z acc =
if z > v1 && z < v2
then z:acc
else acc

如果您愿意,您可以使用防护而不是 if 语句来表达条件,有些人认为这更惯用:

check v1 v2 z acc
| z > v1 && z < v2 = z:acc
| otherwise = acc

关于这两种方式的最后说明

您使用(x:xs)来匹配列表。这意味着您的模式匹配不完整,因此您的函数是部分的,如果您使用空列表调用它,它将在运行时失败。要解决此问题,只需在两个位置将 (x:xs) 更改为单个变量(如 xs),或者完全删除它,因为它位于两个位置的末尾左侧和右侧(这称为 eta 减少)。

关于haskell - 在haskell中无需递归即可进入范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57983381/

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