Tuples

Contents
A pair is a type
fst and snd
zip and unzip
Tuples or records

A pair is a type

A tuple groups values whose types may differ. The arity is part of the type, so a pair and a triple are different things and never mix:

person :: (String, Int) person = ("Ada", 36) point3 :: (Double, Double, Double) point3 = (1.0, 2.0, 3.0)

Destructuring happens in a pattern, so a function can take the parts directly instead of receiving the pair:

birthday :: (String, Int) -> (String, Int) birthday (name, age) = (name, age + 1)

fst and snd

Two standard functions read the halves of a pair. There is no general accessor for larger tuples, because a tuple with many fields is a record waiting to be written:

fst ("Ada", 36) -- "Ada" snd ("Ada", 36) -- 36 -- swap is a one-liner with a pattern swap (a, b) = (b, a)

fst and snd are partial in spirit: they only exist for pairs. For triples, write the pattern.

zip and unzip

zip walks two lists in step and stops at the shorter one. unzip takes a list of pairs back apart:

zip [1,2,3] ["a","b"] -- [(1,"a"),(2,"b")] zipWith (+) [1,2,3] [10,20,30] -- [11,22,33] unzip [(1,"a"),(2,"b")] -- ([1,2],["a","b"])

The silent truncation of zip is convenient and occasionally a bug. When the lengths must agree, check them or use zipWith with a combining function that reports the mismatch.

Tuples or records

A tuple is right for a value that travels a short distance: a function returning two results, a dictionary entry, an accumulator. It becomes wrong when the meaning of each slot must be remembered:

-- hard to read at the call site register ("Ada", 36, True) -- self-documenting, lesson 26 register (Person { name = "Ada", age = 36, active = True })

The rule of thumb: two or three slots used locally are fine, and anything that crosses a module boundary deserves names.

Next: Lists

Article author: Arthur Isaev

Related articles
Haskell
Haskell course: zero to hero in 50 lessons
What is Haskell and why it matters
Install the toolchain with GHCup
GHCi: the interactive shell
Your first program
Values with let and where
Types and type signatures
Functions and application
Currying and partial application
Operators, sections, and fixity
if, guards, and pattern guards
case expressions
Pattern matching
Tuples
Lists
Ranges and enumeration
List comprehensions
Recursion replaces loops
map, filter, and foldr
Lambdas and composition
Type classes
Parametric polymorphism
Maybe and null safety
Either and recoverable errors
data: product types
data: sum types
Records
newtype and type synonyms
Recursive data: binary trees
Functor
Applicative
Monad
do notation
IO and purity
Files and IO
Modules and imports
Cabal projects
Dependencies
Testing with HUnit
Property testing with QuickCheck
Laziness and infinite lists
Strictness and space leaks
Folds
Monoids
Traversable
Monad transformers
Errors and exceptions
Concurrency
Parsing with Megaparsec
Capstone: a todo CLI
Hero roadmap: the whole course on one page
Banner image

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.com
Write to info@aredel.com if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: