haskell - 删除满足谓词的第一个元素(Haskell)

我想创建一个函数,删除满足第二个参数中给定谓词的第一个元素。像这样:

removeFirst "abab" (< 'b')  = "bab"
removeFirst "abab" (== 'b') = "aab"
removeFirst "abab" (> 'b')  = "abab"
removeFirst [1,2,3,4] even  = [1,3,4]

我想通过递归的方式做到这一点,并想出了这个:

removeFirst :: [a] -> (a -> Bool) -> [a]
removeFirst [] _ = []
rremoveFirst (x:xs) p = if p x then x : removeFirst xs p else removeFirst xs p

(灵感来自 this 问题) 但是我得到了一个类型错误,就像这样:

Couldn't match type ‘a’ with ‘Bool’
  Expected: [Bool]
    Actual: [a]
  ‘a’ is a rigid type variable bound by
    the type signature for:
      removeFirst :: forall a. [a] -> (a -> Bool) -> [a]

或者这个:

ghci> removeFirst [1,2,3,4] even

<interactive>:25:1: error:
    * Variable not in scope: removeFirst :: [a0] -> (a1 -> Bool) -> t
    * Perhaps you meant `rem' (imported from Prelude)

我知道这是一个相对简单的程序,我只是对 Haskell 还不够熟悉。我怎样才能做到这种“Haskell 风格”(一行)?

最佳答案

在“以风格”做之前,为什么不先简单地,这样它就可以了。这就是我们学习的方式。

Variable not in scope: removeFirst ...”只是意味着您还没有定义名为 removeFirst 的函数。

所以看起来您首先尝试定义它(并且您显示的错误与您显示的代码一致),然后您遇到了错误,因此它没有被定义,然后您尝试调用它并自然而然地收到错误消息说它尚未定义。

因此,将您的程序保存在源文件中,然后在 GHCi 中加载该文件。然后,如果您遇到任何错误,请将文件中的完整代码复制并粘贴到您的问题中(不要手动重新输入)。还请说明当您收到错误消息时您做了什么,准确地说。并确保通过复制粘贴来完整包含错误消息。

然后您的代码逻辑可以得到解决。


由于其他人已经发布了工作代码,以下是我将其编码为单行代码的方式:

remFirst :: [a] -> (a -> Bool) -> [a]
remFirst xs p = foldr g z xs xs
  where
  g x r ~(_:tl)      -- "r" for recursive result
     | p x           -- we've found it, then
       = tl          -- just return the tail
     | otherwise
       = x : r tl    -- keep x and continue
  z _  = []          -- none were found

缩短了,就变成了

remFirst xs p = 
  foldr (\x r ~(_:tl) -> if p x then tl else x : r tl)
        (const []) xs xs

https://stackoverflow.com/questions/69326029/

相关文章:

c# - 在 C# 中,如何使用 `TryAsync` 的实例?

arrays - Ruby - 根据可能性从数组中选择一个元素

python - 与 return 语句一起使用 'elif' 或连续的 'if' 语句更好吗?

python - 断言一个数字是二进制的

node.js - 类型错误 : Cannot read property 'passport' o

c - 尝试将二维字符串数组传递给函数并打印它

php - 路径在本地主机上有效,但在服务器上无效

objective-c - Rust Cocoa - 如何迭代 NSArray

javascript - Cypress 最佳实践 - 存储和比较两个值

c# - 通过列表循环 foreach,为不同的值执行代码