Haskell Cheatsheet

Types and Signatures

Use this Haskell reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Type Signatures

square :: Int -> Int
square x = x * x

hypotenuse :: Double -> Double -> Double
hypotenuse a b = sqrt (a * a + b * b)

Read a -> b -> c as a function that takes a, then b, then returns c. All Haskell functions technically take one argument because functions are curried.

Type Inference

Haskell infers types, but explicit signatures are still recommended for top-level functions.

triple x = x * 3
-- ghci: :type triple
-- triple :: Num a => a -> a

Num a => is a constraint: the type a must support numeric operations.

Constraints in Practice

showAll :: Show a => [a] -> String
showAll = unwords . map show

between :: Ord a => a -> a -> a -> Bool
between lo hi x = lo <= x && x <= hi

sumAny :: (Foldable t, Num a) => t a -> a
sumAny = sum

Multiple constraints go in a parenthesized tuple before =>.

Common Typeclasses

TypeclassMeaningExamples
Eqequality==, /=
Ordordering<, >, compare
Showconvert to stringshow x
Readparse from stringread "123", readMaybe
Numnumeric operations+, *, abs
Integralwhole numbersdiv, mod
Fractionaldivision/, recip
Semigroupassociative combine<>
Monoidcombine with identitymempty, mconcat
Functormap inside contextfmap, <$>
Foldablereduce a structurefoldr, sum, toList
Traversablemap with effectstraverse, sequenceA
Applicativeapply wrapped functions<*>, pure
Monadsequence dependent actions>>=, do

Type Synonyms

type UserId = Int
type Name = String

formatUser :: UserId -> Name -> String
formatUser uid name = show uid ++ ": " ++ name

A type synonym improves readability but does not create a distinct runtime type. Use newtype when you want the compiler to keep types apart.

Conversions

fromIntegral (length xs) :: Double  -- Int to any Num
realToFrac (3.2 :: Float) :: Double
show 42                 -- "42"
round 3.7               -- 4
floor 3.7               -- 3
ceiling 3.1             -- 4
truncate (-3.7)         -- -3, toward zero

Parsing: read vs readMaybe

import Text.Read (readMaybe)

read "42" :: Int              -- 42, but CRASHES on bad input
readMaybe "42" :: Maybe Int   -- Just 42
readMaybe "4x" :: Maybe Int   -- Nothing

read @Int "42"                -- TypeApplications form (on by default in GHC2021)

read is partial. Any time the input can be invalid (user input, files, network), use readMaybe and handle the Nothing case.