2016-01-14 4 views
4

В introductory text for Template Haskell одним из примеров использования шаблона Haskell является работа с произвольными размерами кортежей.Почему полезны кортежи произвольного размера? (Template Haskell)

Какова цель произвольного размера кортежей? Если тип данных тот же, почему бы не использовать список? И если типы данных в кортеже различаются, как его можно развернуть до произвольных размеров?

+0

Я чувствую необходимость упомянуть [библиотеку «tuple-th»] (http://hackage.haskell.org/package/tuple/th), которую я нашел очень полезной в своей практике. –

ответ

12

С произвольно один означает произвольное во время компиляции. Поэтому, если вы хотите кортежи с пятнадцатью элементами, шаблон Haskell будет генерировать функцию для кортежа с пятнадцатью элементами. Однако после компиляции число элементов фиксировано. Преимущество использования кортежа состоит в том, что вы можете получить доступ к каждому элементу за постоянное время O (1). Таким образом, вы можете использовать систему типов для обеспечения соблюдения кортежа по-прежнему содержит фиксированное количество элементов.

Кроме того, sel в примере может работать с кортежами, где элементы имеют произвольные типы. Например sel 2 3 сгенерирует функцию:

$(sel 2 3) :: (a,b,c) -> b 
$(sel 5 5) :: (a,b,c,d,e) -> e 

в то время как если вы используете список [a], это означает, что список может содержать только данные для определенного типа:

(!!3) :: [a] -> a 

так что все элементы имеют тип a. Кроме того, в этом случае вы не уверены, что в списке будет три элемента. Чем больше вы можете проверить во время компиляции, тем более безопасным будет ваш код (и во многих случаях более эффективный).

список с другой стороны, имеет произвольный размер во время выполнения. Один и тот же тип - например, [Int] - может указывать список с двумя, пятью, целыми или целыми целыми числами. Кроме того, в случае списка доступ к элементу k требует O (k) времени. Существуют такие структуры данных, как массивы, которые, конечно же, могут обращаться к элементам в постоянное время.

+0

Не лучше ли было бы использовать новый тип данных? Подобно 'data X = A Int | B Char | C String' или что-то в этом направлении? – Akaberto

+0

@Akaberto: Я бы не стал выступать за это по нескольким причинам: (а), как было сказано ранее, компилятор не может сделать много проверок, которые могут решить многие проблемы, (б) количество типов бесконечно, и поэтому необходимо узнать, что означает 'A',' B', ... означает (c), что вы будете делать с полиморфными типами (d), это более неэффективно, так как это подразумевает другое косвенное, ... –

+0

К сожалению, я имел в виду нечто вроде 'data Person = Person {firstName :: String, lastName :: String, age :: Int} ' Разве это не похоже на кортеж? – Akaberto