Haskell - разделить список пар на два списка, используя fold - PullRequest
0 голосов
/ 10 января 2019

Итак, я получил список, содержащий кортежи, и мне нужно разбить его на два списка: первый список, содержащий элементы с нечетным индексом, и второй список, содержащий элементы с четным индексом, должны быть выполнены с использованием Fold, здесь моя попытка:

breakList :: [(Integer, Integer)] -> [[(Integer, Integer)]]
breakList [] = [[], []]
breakList xxs@(x:xs) = foldl (\ acc y -> if length (acc !! 0) < length (acc !! 1) then y : (acc !! 0) else y : (acc !! 1)  )  [[], []] xxs

Ошибка, которую я получаю:

Невозможно найти тип '(целое, целое)' с '[(Integer, Integer)]' Ожидаемый тип: [[(Integer, Integer)]]

при наведении на y : (acc !! 1) and y : (acc !! 0)

Пример:

Введите:

ex1 = [(2, 2), (1, 3), (2, 3), (2, 4), (3, 5), (0, 2), (2, 1), (1 4) , (2, 0), (1, 2), (3, 1), (1, 0)]

выход

breakList ex1 == ([(2,2), (2,3), (3,5), (2,1), (2,0), (3,1)], [(1,3), (2 , 4), (0,2), (1,4), (1,2), (1,0)])

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Стандартный прием, на который намекал Виллем в комментариях, которые я впервые увидел несколько лет назад на SO в ответе (F # или Ocaml) [user: Ed'ka], это

evenodds :: [a] -> ([a], [a])
evenodds xs = foldr g ([],[]) xs
  where
  g x ~(as,bs) = (bs,x:as)

или

oddevens :: [a] -> ([a], [a])
oddevens xs = foldr g ([],[]) xs
  where
  g x ~(bs,as) = (x:as,bs)

Что такое нечетные позиции отсюда, это четные позиции с позиции на одну ступеньку дальше в списке.

В тильде ~ вводится ленивый шаблон, поэтому функция должным образом ленива в своих операциях.

0 голосов
/ 10 января 2019

Обратите внимание, что вы хотите разбить список на два списка пары, поэтому тип возвращаемого значения должен быть

([(Integer, Integer)], [(Integer, Integer)])

не

[[(Integer, Integer)]]

и доступ к элементу пары, вы можете использовать fst и snd вместо сквозного индекса, и, наконец, использование foldl вернет полученный список в обратном порядке, его можно исправить, используя foldr , Коррекция выглядит так:

breakList :: [(Integer, Integer)]->([(Integer, Integer)], [(Integer, Integer)])
breakList xxs = foldr (\y acc-> if length (fst acc) < length (snd acc)
                                then (y:(fst acc), snd acc)
                                else (fst acc, y:(snd acc)) ) ([], []) xxs
...