I've been doing a lot of work with tuples and lists of tuples recently and I've been wondering if I'm being sensible.
Things feel awkward and clunky which for me signals that I'm doing something wrong.
For example I've written three convenience functions for getting the first, second and third value in a tuple of 3 values.
Is there a better way I'm missing?
Are there more general functions that allow you to compose and manipulate tuple data?
Here are some things I am trying to do that feel should be generalisable.
Extracting values: Do I need to create a version of fst,snd,etc... for tuples of size two, three, four and five, etc...?
fst3(x,_,_) = x
fst4(x,_,_,_) = x
Manipulating values: Can you increment the last value of every tuple in a list of pairs and then use that same function to increment the last value of every tuple in a list of triples?
Zipping and Unzipping values: There is a zip and a zip3. Do I also need a zip4? or is there some way of creating a general zip function?
Sorry if this seems subjective, I honestly don't know if this is even possible or if I'm wasting my time writing 3 extra functions every time I need a general solution.
Thank you for any help you can give!
Yes, you need to write fstN
yourself. But why not extract it in pattern matching?
Data.List already provides up to zip7
. For general zipN
, use a ZipList.
See How to zip multiple lists in Haskell?.
Not without extensions. Since all tuples are of different types, you have to create a type class, for example:
{-# 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)
Then you could use
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
is similar.)
But why not use separate functions?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With