填充由两个列表组成的元组

Filling a Tuple consisting of two lists

我正在尝试在我的函数中填充一个由两个列表组成的元组,并且根据条件我想在这个元组中分别填充一个不同的列表。代码如下:

type One = []
type Two = []

bar :: Int -> Bool
bar ... 

foo :: Somelist -> (One, Two)
foo somelist
  | null somelist = ([],[])
  | bar yesno = {-I want to fill the list "One" here if bar == true-} foo (tail somelist)
  | otherwise = {-and the list "Two" here if bar == false-}           foo (tail somelist)

什么是解决这个问题的优雅而巧妙的方法:)?

感谢您的建议。

与您的示例相比,我稍微更改了类型以使代码可测试。

type One = [Integer]
type Two = [Integer]

bar :: Integer -> Bool
bar x = x > 0 

foo :: [Integer] -> (One, Two)
foo [] = ([], [])
foo (x:xs)
  | bar x =  (x:one, two)
  | otherwise = (one, x:two) where
    (one, two) = foo xs

快速测试:

λ> foo [-10..10]
([1,2,3,4,5,6,7,8,9,10],[-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0])

想法是向下递归到列表的末尾和 return 列表的元组,然后在递归堆栈上,从函数中获取 returning 元组并根据您的谓词将当前元素的值添加到列表中。

或者您可以使用 Data.List 中的 partition,类型为 partition :: (a -> Bool) -> [a] -> ([a], [a])。这个函数接受一个列表和一个谓词,return 是一个包含 2 个列表的元组:一个是谓词 return 为真,另一个是 return 为假。

import Data.List (partition)

foo2 :: [Integer] -> (One, Two)
foo2 xs = partition bar xs

您可以减少上述内容,但为了清楚起见,我没有这样做。