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

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

[1,2,3,4,5,6] -> (1,2,3,4,5,6)
26
задан P Shved 27 May 2010 в 14:58
поделиться

4 ответа

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

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

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

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

... но не одну, которая выполняла бы обе функции.

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

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

48
ответ дан 28 November 2019 в 06:06
поделиться

Шаблонный 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 (\x y -> 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')

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

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

24
ответ дан 28 November 2019 в 06:06
поделиться

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

2
ответ дан 28 November 2019 в 06:06
поделиться

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

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

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

7
ответ дан 28 November 2019 в 06:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: