5

aのリストとのリストを取得し、bすべてのペアリング [(a, b)] を返すように設計された次のコードがあります。

  • それぞれはab各ペアリングで 1 回だけ表示されます。
  • 各ペアは、いくつかの条件を(a, b)満たしています。condcond :: a -> b -> Bool

たとえば、リスト [1, 2] [x,y,z] の結果は次のようになります。

[[(1, x), (2, y)]
 [(1, x), (2, z)]
 [(1, y), (2, x)]
 [(1, y), (2, z)]
 [(1, z), (2, x)]
 [(1, z), (2, y)]]

これは、明示的な再帰を使用してジョブを実行する (やや抽象化された) コードですが、フォールドまたは類似のものに置き換えたいと考えています。任意のヒント?

someFn :: [a] -> [b] -> [ [(a, b)] ]
someFn [] _ = []
someFn (a : as) bs = [ [(a,b)] ++ rest | b <- bs, rest <- someFn as (bs \\ [b]), cond a b]
4

2 に答える 2

5

あなたの説明から私が理解できるのは、2つのリストの積の条件に基づいてフィルタリングしたいということです。リスト内包表記を使用してリストの積を取得するのは簡単で、フィルター関数は積を特定の条件を満たすペアのみに減らします

foo :: [a] -> [b] -> (a -> b -> Bool)-> [(a,b)]
foo x y with = filter (uncurry with) [(a,b) | a <- x, b <- y] 

[編集に応じて更新]

これにより、必要なリストが生成されます(うまくいけば)

bar :: [a] -> [b] -> [[(a,b)]]
bar xs ys = map (zip xs) $ permutations ys

特定の条件でフィルタリングするには

biz :: (a -> b -> Bool) -> [[(a,b)]] -> [[(a,b)]]
biz = map . filter . uncurry
于 2013-10-10T16:05:13.370 に答える
0

a を使用しfoldrて、次のようにコードをリファクタリングできます。

delete :: Int -> [a] -> [a]
delete index xs = let (ys, _:zs) = splitAt index xs in ys ++ zs

ifoldr :: (Int -> a -> b -> b) -> b -> [a] -> b
ifoldr f acc xs = foldr (\(a, b) c -> f a b c) acc $ zip [0..] xs

someFn :: (a -> b -> Bool) -> [a] -> [b] -> [[(a,b)]]
someFn _ [] _ = [[]]
someFn cond (a:as) bs = ifoldr (\index b acc -> if cond a b
    then concat [map ((a,b):) . someFn cond as $ delete index bs, acc]
    else acc) [] bs

エッジケースはsomeFn _ [] _ = [[]]、関数の型定義に従っていることに注意してくださいsomeFn :: (a -> b -> Bool) -> [a] -> [b] -> [[(a,b)]]

someFn次のように使用できます。

someFn (\a b -> True) [1,2] "xyz"

-- [[(1,'x'),(2,'y')],
--  [(1,'x'),(2,'z')],
--  [(1,'y'),(2,'x')],
--  [(1,'y'),(2,'z')],
--  [(1,'z'),(2,'x')],
--  [(1,'z'),(2,'y')]]

someFn (\a b -> case (a,b) of (1,'x') -> False
                              (2,'y') -> False
                              otherwise -> True) [1,2] "xyz"

-- [[(1,'y'),(2,'x')],
--  [(1,'y'),(2,'z')],
--  [(1,'z'),(2,'x')]]

それが役立つことを願っています。

于 2013-10-10T18:26:02.557 に答える