【问题标题】:Haskell get the position of an item in a listHaskell 获取列表中项目的位置
【发布时间】:2018-08-10 14:16:08
【问题描述】:

我刚刚开始学习 Haskell,我真的有很多关于它的问题。在我正在做的教程中,我需要开发一个功能,在其中从列表和某个字符串中,您将找到字符串在列表中的位置。网上搜索找到了这段代码,但实在看不懂,谁能给我解释一下。

lookUp :: [String] -> String -> Int
lookUp [] s = error "String no encontrado"
lookUp (x:xs) s | not(x == s) = 1 + (lookUp xs s)
                | otherwise = 0

【问题讨论】:

  • 这看起来是一种相当丑陋的解决方法:使用否定逻辑,errors, ... :(
  • 请提出具体问题。如果这段代码的每一部分对你来说都没有意义,那么这个问题对于 StackOverflow 来说可能太宽泛了。
  • 如果写成lookup (x:xs) s = if x == s then 0 else (1 + lookup xs s)你会理解得更好吗?
  • 你能具体说明你不了解的地方吗?语法、类型、递归、模式匹配?
  • 对不起,如果我没有进一步详细说明,就像下面那样,我正在寻找有人详细说明代码的每个部分。

标签: string list haskell


【解决方案1】:
lookUp :: [String] -> String -> Int
lookUp [] s = error "..."  -- An empty list does not contain _anything_, in
                           -- particular not the string you're looking for.
lookUp (x:xs) s     -- We've eliminated the empty case, which guarantees there's
                    -- at least one (head) element in the list if we get here.
                    -- Let's examine it!
   | not (x == s) -- If the element isn't the one we were looking for...
       = 1 + (lookUp xs s)   -- then we need to continue the search, i.e. search
                             -- through the _remaining_ elements `xs` and, if `s` is
                             -- found there, report a one higher position (because
                             -- we've already skipped one element).
   | otherwise  -- Else, the element _is_ the one we were looking for...
       = 0   -- IOW, it occurs at position 0 of the (part of) the list we're
             -- currently examining.

多说几句:

  • 正如 Willem Van Onsem 评论的那样,error 在这里是个坏主意:这是一个现实场景,列表不包含您正在寻找的元素,即这不仅仅是一个“哎呀,流星罢工破坏了银行的财务”,但您应该预料到的实际风险。但是error 默认情况下会使整个程序崩溃。相反,您应该返回 Maybe Int,它允许您以调用者可以轻松处理的方式发出失败信号。

    lookUp :: [String] -> String -> Maybe Int
    lookUp [] _ = Nothing
    lookUp (x:xs) s | not(x == s)  = fmap (1 +) (lookUp xs s)
                    | otherwise    = Just 0
    
  • 此函数中的任何内容实际上都不需要列表中的字符串。它同样适用于整数、单个字符、布尔值等。任何允许相等比较的东西。因此,您不妨签名

    lookUp :: Eq a => [a] -> a -> Maybe Int
    

【讨论】:

  • 非常感谢您的回答,非常有帮助,我会做出建议的修改。
【解决方案2】:
lookUp :: [String] -> String -> Int

函数查找接受字符串列表和返回 Int 的字符串

lookUp [] s = error "String no encontrado"

如果第一个参数是空字符串,则返回error ...

lookUp (x:xs) s | not(x == s) = 1 + (lookUp xs s)
                | otherwise = 0

有趣的部分(x:xs) 从列表中获取第一个字符串,然后字符串 | 是守卫,所以如果x 中的字符串不等于s 字符串return 1 + ( lookup xs s) .. ==> 递归调用lookUpxs - 没有比较字符串x 和字符串@ 的字符串列表987654333@作为参数

最后othervise返回0

手动:

lookUp [] "foo" ==> 第一个模式 [] 所以返回错误

lookUp ["foo"] "foo" ==> 第二个模式并运行 guard ==> not( "foo" == "foo") = 1 + ( lookUp [] "foo") ,这在第二行结束 othervise 0 所以它返回正确的位置 0

lookUp [ "bar", "foa", "foo", "fao" ] "foo" ==> 第二个模式并扩展为:not ( "bar" == "foo") return 1 + (lookUp ["foa", "foo", "fao"] "foo") 然后 not( "bar" == "foo") return 1 + (not ("foa" == "foo") = return 1 + (lookUp ["foo", "fao"] "foo")) 然后 not( "bar" == "foo") return 1 + (not ("foa" == "foo") = return 1 + (not("foo" == "foo") = return 1 ).. but because now test is *True* usesothervise = 0so1+1 = 2and2` 是列表中正确的字符串位置。

最后一种可能性:

lookUp ["bar"] "foo" ==> not("bar" == "foo") = return 1 + (lookUp [] "foo")lookUp 带有空列表会引发错误

【讨论】:

  • 非常感谢您的回答,非常有帮助,我真的需要所有详细信息。
猜你喜欢
  • 1970-01-01
  • 2015-10-26
  • 2010-09-26
  • 2018-09-21
  • 2016-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-11
相关资源
最近更新 更多