【问题标题】:How do you detect if a list has exactly 3 items in Haskell?你如何检测一个列表在 Haskell 中是否正好有 3 个项目?
【发布时间】:2010-03-19 21:05:55
【问题描述】:

我有这个,但我遇到了一个错误:

-- test if a list contains exactly three characters
test :: [Char] -> Bool
test xs   | [_ , _ , _] = True
          | otherwise = False

【问题讨论】:

  • 我不得不说,比起[_ , _ , _],我更喜欢[_, _, _]
  • 你遇到了什么错误?
  • 这里的答案比我要求的要多。谢谢。

标签: list haskell syntax


【解决方案1】:

我会写一些类似的东西

hasLength3 :: [a] -> Bool
hasLength3 xs = xs `hasLength` 3

hasLength :: [a] -> Int -> Bool
hasLength = foldr go stop
  where
    go _ r n = n > 0 && r (n - 1)
    stop n = n == 0

【讨论】:

    【解决方案2】:

    模式匹配发生在垂直条的左侧。因此:

    test :: [Char] -> Bool
    test [_, _, _] = True
    test _         = False
    

    正如Norman Ramsey 在下面正确指出的那样,以下代码不是可靠的替代解决方案(因为它在应用于(长)有限列表时效率非常低,并且不会在无限列表上停止)和因此应该使用:

    test :: [Char] -> Bool
    test xs = length xs == 3
    

    此外,length xs == 0 应始终替换为 null xs

    编辑:自然会出现的问题是:我们如何概括这个?如果我们想测试一个列表是否恰好有 n 元素?如果输入可能是无限的怎么办? 这是一个解决方案,其中成本是 n 或列表的长度,以较小者为准——这是一个渐近的高效解决方案,正如我们所希望的那样:

    hasLength :: Int -> [a] -> Bool
    hasLength n []     = n == 0
    hasLength 0 (x:xs) = False
    hasLength n (x:xs) = hasLength (n-1) xs
    

    用法:

    *Main> hasLength 3 [1..2]
    False
    *Main> hasLength 3 [1..3]
    True
    *Main> hasLength 3 [1..4]
    False
    *Main> hasLength 3 [1..] 
    False
    

    用负长度调用这个函数是不安全的;如果列表是无限的,则函数不会终止,如果列表是有限的,它将返回False,其成本与列表的长度成正比。一个简单的修复方法是提前检查(仅在第一次调用时)n 是非负数,但这种修复会使代码变得丑陋。

    【讨论】:

    • 呃!在length 示例之前,我一直与您同在。这太接近一个经典的初学者错误:写length xs == 0而不是null xs
    • 或者如果你想变得花哨,我认为无点形式是test = (3 ==) . length
    • @MatrixFrog:请不要!!! @Stephan:null 无法解决这个问题。我的意思是,我没有明确说明的是,许多初学者在应该使用null 或模式匹配时使用length。鼓励length 作为解决这个问题的方法是鼓励不计成本的编程,以及在无限列表上失败的编程。另一方面,您的 hasLength 功能更正确。我要编辑;如果您不喜欢这些编辑,请将它们回滚。如果您确实喜欢它们,请从您的答案中删除length,以便我对其进行投票:-)
    • @Norman:感谢您的澄清!随意编辑并删除对length 的引用。当您使用它时,添加import Data.List :)
    • 我选择在使用length的代码上方添加一个明确的警告,而不是完全删除它;那更有教育意义。 hasLength 的替代实现不需要import Data.List
    【解决方案3】:
    main = do
      a:b:c:[] <- pure "123"  -- fails in runtime in MonadFail if they are not exactly 3
      print a >> print b >> print c
    

    【讨论】:

      猜你喜欢
      • 2019-07-26
      • 2017-02-10
      • 1970-01-01
      • 2022-08-24
      • 2014-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多