使用示例更容易解释这一点:
我想编写一个函数[a]-> [(a,a)],以便获得列表
[A, B, C, D]
我希望此列表返回:
[(A, A), (A,B), (A,C), (A,D), (B,B), (B,C), (B,D), (C,C), (C,D), (D,D)]
我想到了以下代码:
function s = [(x,y) | x <- s, y <- s, x<=y]
这对于整数列表可以正常工作,但是我希望它对不是Ord类实例的数据类型起作用。我的数据类型派生Show和Eq。有没有简单的方法可以解决这个问题?我在想也许是通过过滤
中的元组function s = [(x,y) | x <- s, y <- s]
但是我也不知道该怎么做。
答案 0 :(得分:5)
使用递归的解决方案:
f :: [a] -> [(a, a)]
f [] = []
f (x:xs) = [(x, y) | y <- (x:xs)] ++ f xs
无递归:
import Data.List (tails)
f' :: [a] -> [(a, a)]
f' xs = concat [[(head x, y) | y <- x] | x <- tails xs]
没有列表理解:
import Data.List (tails)
f'' :: [a] -> [(a, a)]
f'' xs = concatMap (\sl -> zip (repeat $ head sl) sl) (tails xs)
最好的是丹尼尔·瓦格纳(Daniel Wagner),只需使用
[(head x, y) | x <- tails xs, y <- x]
答案 1 :(得分:2)
这是一个嵌套循环。
import Data.List (dropWhile)
com xs = do
x <- xs
y <- dropWhile (/= x) xs
return (x, y)
答案 2 :(得分:1)
您可以使用scanr
f l = zip l (scanr (:) [] l) >>= \(h,t) -> fmap ((,) h) t
首先,您将获得l
的(头,尾)列表,将图尾与相应的头配对的图尾,最后将所有内容展平。
答案 3 :(得分:0)
继续使用过滤器[(x,y) | x <- xs, y <- xs]
的想法,您可以使用foldl代替:
f = foldl add []
where add ys (a,b) | notElem (b,a) ys = (a,b):ys
| otherwise = ys
g xs = [(x,y) | x <- xs, y <- xs]
function = f . g