Хорошие функции и методы для контакта с haskell кортежами?

Я делал большую работу с кортежами и списками кортежей недавно, и я задавался вопросом, разумен ли я.

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

Например, я записал три функции удобства для получения первого, второго и третьего значения в кортеже 3 значений.

Существует ли лучший способ, которым я отсутствую?

Есть ли более общие функции, которые позволяют Вам составлять и управлять данными кортежа?

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

Извлечение значений: я должен создать версию fst, snd, и т.д.... для кортежей размера два, три, четыре и пять, и т.д....?

fst3(x,_,_) = x
fst4(x,_,_,_) = x

Управление значениями: можно ли увеличить последнее значение каждого кортежа в списке пар и затем использовать ли ту же самую функцию для постепенного увеличения последнего значения каждого кортежа в списке, утраивается?

Архивирование и Разархивация значений: существует zip и zip3. Мне также нужен zip4? или есть ли некоторый способ создать общую функцию zip?

Извините, если это кажется субъективным, я честно не знаю, возможно ли это даже или если я трачу впустую свое время, пишущий 3 дополнительным функциям каждый раз, когда мне нужно общее решение.

Спасибо за любую справку можно дать!

5
задан Don Stewart 18 April 2011 в 23:30
поделиться

5 ответов

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

data LatticeOperations a = LO { bot :: a
                              , top :: a
                              , glb :: a
                              , lub :: a
                              , le  :: a
                              }

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

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

lattice { le = le', glb = glb', lub = lub' }

И, конечно, если у вас есть большая запись и вы просто пытаетесь для увеличения вы можете сделать что-то вроде

data FatRecord = FR { count :: Int, ... }

fat = fat { count = count fat + 1 }

Я не думаю, что синтаксис записи помогает с zip и unzip.

7
ответ дан 18 December 2019 в 06:49
поделиться

Нет способа обобщить кортеж -size без использования расширений, таких как Template Haskell. Итак, если мы просто рассмотрим простой haskell: да, вам нужно написать версии fst и т. Д. Для каждого размера кортежа, и нет, вы не можете написать общий метод zip.

2
ответ дан 18 December 2019 в 06:49
поделиться

Извлечение значений

Да, вам нужно написать fstN себя.Но почему бы не извлечь его при сопоставлении с образцом?

Сжатие и разархивирование значений

Data.List уже предоставляет до zip7 . Для общего zipN используйте ZipList.

См. Как заархивировать несколько списков в Haskell? .

Управление значениями

Не без расширений. Поскольку все кортежи имеют разные типы, вам необходимо создать класс типа, например:

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies #-}

class Firstable a b c | a -> b, a -> c where
    firstOf :: a -> b
    restOf :: a -> c
    concatenate :: b -> c -> a

instance Firstable [a] a [a] where
    firstOf = head
    restOf = tail
    concatenate = (:)

instance Firstable (a,b) a b where
    firstOf = fst
    restOf = snd
    concatenate = (,)

instance Firstable (a,b,c) a (b,c) where
    firstOf (x,_,_) = x
    restOf (_,x,y) = (x,y)
    concatenate x (y,z) = (x,y,z)

instance Firstable (a,b,c,d) a (b,c,d) where
    firstOf (x,_,_,_) = x
    restOf (_,x,y,z) = (x,y,z)
    concatenate x (y,z,w) = (x,y,z,w)

instance Firstable (a,b,c,d,e) a (b,c,d,e) where
    firstOf (x,_,_,_,_) = x
    restOf (_,x,y,z,w) = (x,y,z,w)
    concatenate x (y,z,w,t) = (x,y,z,w,t)

Затем вы можете использовать

incFirst :: (Num b, Firstable a b c) => a -> a
incFirst x = (1 + firstOf x) `concatenate` restOf x

main = do
    print $ map incFirst [(1,2),(3,4),(5,6)]
    print $ map incFirst [(1,3,6,7),(2,5,-2,4)]

( lastOf аналогично.)

Но почему бы не использовать отдельные функции ?

8
ответ дан 18 December 2019 в 06:49
поделиться

Как только кортежи становятся больше размера 3 или около того, и/или один и тот же тип кортежа начинает широко использоваться, лучше использовать запись.

4
ответ дан 18 December 2019 в 06:49
поделиться

Встроенные в Haskell fst и snd поддерживают только пары кортежей, поэтому вы вправе определить свои собственные. Если вы хотите увеличить последнее значение в списке, разверните список, работайте с этого конца и разверните его обратно. Если вы хотите, чтобы инкремент работал для списков и списков кортежей, просто определите новую функцию инкремента для этих типов данных и вызовите ее внутри вашей функции инкремента для списка. @KennyTM ответил на вопрос zipN.

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

0
ответ дан 18 December 2019 в 06:49
поделиться
Другие вопросы по тегам:

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