如何编写一个函数来计算列表中严格大于和严格小于给定数字的元素数量?

Ale*_*rov 4 haskell functional-programming

我正在尝试通过本课程学习 Haskell ,但我对第一个模块中的最后一个作业有点困惑。问题陈述听起来如下:

编写一个函数,它接受一个数字和一个数字列表并返回一个字符串,说明列表中有多少元素严格大于给定数字并严格小于给定数字。

lowerAndGreater 3 [1 .. 9]
"3 is greater than 2 elements and lower than 6 elements"
Run Code Online (Sandbox Code Playgroud)

解释:列表 [1 .. 9] 包含 9 个元素: [1, 2, 3, 4, 5, 6, 7, 8, 9] 给定数字 3 大于 2 个元素(1 和 2)且小于6 个元素(4、5、6、7、8 和 9)。

提示:使用递归来实现此功能。

这是我解决问题的尝试:

lowerAndGreater :: Int -> [Int] -> String
lowerAndGreater n list = show(n) ++ " is greater than " ++ show(lesserThanN n list) ++ " elements and lower than " ++ show(greaterThanN n list) ++ " elements"
    where
        greaterThanN :: Int -> [Int] -> Int
        greaterThanN greater l =
            if null l
            then greater
            else if head l > n
                 then greaterThanN (greater + 1) (tail l)
                 else greaterThanN greater       (tail l)

        lesserThanN :: Int -> [Int] -> Int
        lesserThanN lesser l =
            if null l
            then lesser
            else if head l < n
                 then lesserThanN (lesser + 1) (tail l)
                 else lesserThanN lesser       (tail l)
Run Code Online (Sandbox Code Playgroud)

不幸的是,执行结果不是我所期望的,例如

lowerAndGreater 3 [1 .. 9]
"3 is greater than 5 elements and lower than 9 elements"
Run Code Online (Sandbox Code Playgroud)

你能告诉我我的错误在哪里吗?

Wil*_*sem 5

一次性枚举该列表可能会更好。我们可以使用返回 2 元组的函数来完成此操作:

import Control.Arrow (first, second)

lowerAndGreater :: Ord a => a -> [a] -> (Int, Int)
lowerAndGreater y = foldr go (0, 0)
  where
    go x
        | x < y = first (+ 1)
        | x > y = second (+ 1)
        | otherwise = id
Run Code Online (Sandbox Code Playgroud)

这给了我们:

ghci> lowerAndGreater 3 [1 .. 9]
(2,6)
Run Code Online (Sandbox Code Playgroud)