【问题标题】:Haskell Recursive Adding Function Not WorkingHaskell递归添加功能不起作用
【发布时间】:2020-03-28 17:14:55
【问题描述】:

我尝试编写一个 Haskell 函数来递归地确定列表是否在任意值之下。由于某种原因,代码未编译。我的错误如下。

--declare function
checkIfExpensive :: [Float] -> Float -> String

--base case
checkIfExpensive [] x = "You have enough money"
checkIfExpensive list x = if x > 20
--recursive case
                                then "You don't have enough money"
                                else checkIfExpensive (init list) (last list + x)

编辑:通过将“tail”切换到“last”来编译代码。但是,现在我每次运行代码时似乎都会遇到不同的错误。

下面是一些错误的样子

*Main> checkIfExpensive [5,5,5] 0

<interactive>:1:1: error: Data constructor not in scope: Ixve5
*Main> checkIfExpensive [1,1,1] 0

<interactive>:1:1: error: Variable not in scope: cpe
Prelude>

【问题讨论】:

  • 您确定输入的内容完全符合您的意图吗?正如您所说,考虑到您的预期输入,这些错误毫无意义 - 但它抱怨的变量名是按顺序由预期输入中的字符组成的。所以这几乎就像你的键盘坏了,缺少一些字符不显示? (但是我不知道你是如何输入你的帖子的,包括示例 GHCi 会话......)
  • 您无法从此命令中得到这些错误。如果您的程序中有一些不在范围内的内容,它会在加载程序时显示,而不是在您键入命令时显示。

标签: haskell recursion


【解决方案1】:

列表的尾部表示列表中第一个元素之后的所有内容。 例如,[1, 2, 3, 4] 的尾部就是 [2, 3, 4]。您收到的错误是明智地通知您不能将浮点数添加到浮点数列表中。

tail 函数的实现通过考虑列表数据类型的归纳定义来明确,即列表要么是空的,要么是由一个元素和一个列表构成的。

您之前可能发现此问题的一种方法是观察尾巴的类型,如下所示:

tail :: [a] -> [a]

获取列表最后一个元素的正确方法是使用 last 函数,其类型签名如下:

last :: [a] -> a

我还建议使用all :: (a -&gt; Bool) -&gt; [a] -&gt; Bool 函数来检查某个条件是否适用于整个列表。例如,给定一个浮点列表xs,您可以使用:

all (<= 20) xs

另外,还有any :: (a -&gt; Bool) -&gt; [a] -&gt; Bool。此外,递归列表的惯用方式是在头部和尾部进行模式匹配,例如:

checkIfExpensive :: [Float] -> String
checkIfExpensive [] = "You have enough money"
checkIfExpensive (x:xs)
  | x > 20 = "You don't have enough money"
  | otherwise = checkIfExpensive xs

【讨论】:

  • 我意识到我误解了 tail 函数并将其换成最后一个函数。我的代码现在可以编译,但现在运行该函数时它给了我奇怪的错误。
【解决方案2】:

首先:String 对于您的返回值来说太“大”了。只有两个(无限多)可能的返回值。请改用Bool。 (您始终可以编写单独的函数来选择要显示的消息。)

checkIfExpensive :: [Float] -> Bool

其次,已经有一个预定义的函数来确定列表中的 any 元素是否满足您的条件:any 函数。

any :: Foldable t => (a -> Bool) -> t a -> Bool

列表是可折叠的,所以你需要写的只是

checkIfExpensive list = any (\x -> x > 20) list

如果你无论如何都想返回Stringif表达式可以测试any的返回值。

checkIfExpensive :: [Float] -> String
checkIfExpensive list = if any (\x -> x > 20) list 
                        then "You don't have enough money"
                        else "You don't have enough money"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-13
    • 1970-01-01
    • 2015-02-21
    • 1970-01-01
    • 1970-01-01
    • 2015-03-19
    • 2012-02-08
    相关资源
    最近更新 更多