Как преобразовать список в кортеж в Haskell?

Как лучше всего преобразовать список в кортеж в Haskell:

[1,2,3,4,5,6] -> (1,2,3,4,5,6) 

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

Например, у вас могут быть такие функции, как:

 tuplify2 :: [a] -> (a,a) tuplify2 [x,y] = (x,y) tuplify3 :: [a] -> (a,a,a) tuplify3 [x,y,z] = (x,y,z) 

… но не тот, который выполняет работу обоих.

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

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

Шаблон Haskell настолько близок, насколько вы можете получить из-за проверки типа, если вы хотите извлечь переменное число элементов, поскольку (a, b) и (a, b, c) имеют разные типы.

 {-# LANGUAGE TemplateHaskell #-} import Language.Haskell.TH tuple :: Int -> ExpQ tuple n = do ns <- replicateM n (newName "x") lamE [foldr (\xy -> conP '(:) [varP x,y]) wildP ns] (tupE $ map varE ns) 

Затем:

 $(tuple 6) [1,2,3,4,5,6] == (1,2,3,4,5,6) $(tuple 3) "abc" == ('a','b','c') 

Но в целом, если вам нужен этот ответ, тогда вы задаете неправильный вопрос где-нибудь.

Если вы просто хотите получить произвольный произвольный доступ, возможно, лучшим вариантом будет использование массива.

Если чувствуете, что я собираюсь посоветовать вам указывать пистолет на ногу и доверять вам не стрелять.

 > list2Tuple lst = read $ "(" ++ (init.tail.show) lst ++ ")" > list2Tuple [1,2,3] :: (Int, Int, Int) (1,2,3) > list2Tuple [1,2,3,4] :: (Int, Int, Int, Int) (1,2,3,4) 

Это будет работать до того, что будет определяться длиной и количеством строк и Show.

Кортежи и списки очень разные. О том, что вы можете сделать, это вручную написать функцию преобразования:

 toTuple :: [a] -> (a,a,a,a,a,a) toTuple [a,b,c,d,e,f] = (a,b,c,d,e,f) 

Обратите внимание, насколько различны типы: единственная переменная списка расширяется до шести переменных для кортежа. Таким образом, вам понадобится одна функция для каждого размера кортежа.

Мне сложно сделать убедительные объяснения манипуляций с шаблоном Хаскелла, но вот демонстрация:

 > :m +Language.Haskell.TH > :set -XTemplateHaskell > runQ [| [1,2,3,4,5,6] |] >>= putStrLn . pprint [1, 2, 3, 4, 5, 6] > runQ [| [1,2,3,4,5,6] |] >>= \ (ListE exps) -> putStrLn (pprint (TupE exps)) (1, 2, 3, 4, 5, 6) 

Я не думаю, что это возможно сделать в Haskell, для списка произвольной длины, неизвестной во время компиляции. Шаблон Haskell не может этого сделать, потому что он работает только во время компиляции. Я столкнулся с ситуацией, когда мне нужно было сделать именно это, и мне пришлось обходиться. Библиотека базы данных ожидает кортежей различной длины для аргументов запроса, но у меня есть список произвольной длины. Поэтому я должен обойти библиотечный интерфейс. Было бы неплохо, если бы он мог взять список.

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

На самом деле вы можете сделать лучше, чем вручную писать одну функцию для каждого размера, если вы используете квазикомиссию [1]. Тем не менее, я бы задался вопросом о коде, где вы ожидаете использовать это в целом.

[1] http://www.haskell.org/haskellwiki/Quasiquotation

  • Проверьте, является ли тип экземпляром Show в Haskell?
  • Префиксная форма унарного оператора в Haskell
  • Имеет ли Haskell переменные?
  • Почему ленивая оценка полезна?
  • Что означает () в Haskell
  • foldl хвост рекурсивный, так как же foldr работает быстрее, чем foldl?
  • Как происходит работа в Haskell?
  • Возвращать определенный тип внутри Haskell
  • В Haskell, когда мы используем это с let?
  • Связь между Java и Haskell
  • Начало работы с Haskell
  • Interesting Posts
    Давайте будем гением компьютера.