Haskell список кортежей в список?

можно ли преобразовать список кортежей [(Int,Int)] как общий способ, который действителен для любого размера ввода ? .. я видел в различных вопросах, что это невозможно вообще

пример :

type X = [(Int,Int)]


func :: X -> [Int]

5 ответов


ваш вопрос не очень уверен в том, как кортежи должны быть преобразованы в список. Я предполагаю, что вы хотите их сгладить - например,[(1,2),(3,4)] должны стать [1,2,3,4].

этот перевод возможен только, если эти два элемента вашего кортежа одного типа, чем вы можете сделать что-то вроде этого:

tupleToList :: [(a,a)] -> [a]
tupleToList ((a,b):xs) = a : b : tupleToList xs
tupleToList _          = []

В общем случае, такой перевод невозможен. Одна вещь, которую я мог себе представить, чтобы сделать невозможное возможным использовать Either в оберните два разных типа:

tupleToList :: [(a,b)] -> [Either a b]
tupleToList ((a,b):xs) = Left a : Right b : tupleToList xs

на объектив библиотека обрабатывает этот и подобные случаи последовательно.

> import Control.Lens
> toListOf (traverse . both) [(1,2),(3,4)]
            ^          ^
            |          |> Traversal of the tuple (a, a)
            |> Traversal of a list [b]
[1,2,3,4]

для преобразования из списка списков:

> toListOf (traverse . traverse) [[1,2],[3,4],[5,6,7]]
[1,2,3,4,5,6,7]

добавление edit:


traverse работает с проходимым

traverse будет работать с любым типом данных, который имеет Traversable например, деревья.

> import Data.Tree
> let t = Node 1 [Node 2 [Node 3 [], Node 4 []], Node 5 []]
> let prettyTree = drawTree . fmap show
> prettyTree t
1
|
+- 2
|  |
|  +- 3
|  |
|  `- 4
|
`- 5
> toListOf (traverse . traverse) [t, t]
[1,2,3,4,5,1,2,3,4,5]

вы также можете использовать складке и избежать явной рекурсии:

tupleToList = foldr (\(f,s) a -> f : s : a) []

или:

tupleToList = foldl (\a (f,s) -> a ++ [f,s]) []

(для элементов одного типа)


это также может быть достигнуто с помощью библиотека однородных кортежей (отказ от ответственности: который я автор). Он определяет обертки для кортежей, которые делают их экземплярами Traversable (и других, таких как Applicative и Monad). Таким образом, Кортеж можно преобразовать в список с помощью toList . Tuple2 (где в список С Data.Foldable) и

f :: [(a, a)] -> [a]
f = concatMap (toList . Tuple2)

вы также можете использовать его для других кортежей, например concatMap (toList . Tuple5) etc.


f [] = []
f [(x, y) : xs] = x : y : f xs