Syntactic sugar is any additional redundant syntax in a programming language that makes the code easier to understand or write.

Summary of the various uses of syntactic sugar in Haskell:

## Functions and constructors

description sweet unsweet
operators
a mappend b
1+2

mappend a b
(+) 1 2

sections
(+2)
(3-)

\x -> x + 2
\x -> 3 - x

unary minus[1]
-x

negate x

tuples[2]
(x,y)

(,) x y


## Lists

description sweet unsweet
lists
[1,2,3]

1:2:3:[]

further desugared to
(:) 1 ((:) 2 ((:) 3 []))

strings
"abc"

['a','b','c']

further desugared to
'a':'b':'c':[]

even furtherly desugared to
(:) 'a' ((:) 'b' ((:) 'c' []))

arithmetic sequences
[1..5]
[1,3..9]
[1..]
[1,3..]

enumFromTo 1 5
enumFromThenTo 1 3 9
enumFrom 1
enumFromThen 1 3

list comprehensions to functions
[ x | (x,y) <- foos, x < 2 ]

let ok (x,y) = if x < 2 then [x] else []
in concatMap ok foos

list comprehensions to list monad functions
[ x | (x,y) <- foos, x < 2 ]

[ (x, bar) | (x,y) <- foos,
x < 2,
bar <- bars,
bar < y ]

foos >>= \(x, y) ->
guard (x < 2) >>
return x

foos >>= \(x, y) -> guard (x < 2) >>
bars >>= \bar ->
guard (bar < y) >>
return (x, bar)
-- or equivalently
do (x, y) <- foos
guard (x < 2)
bar <- bars
guard (bar < y)
return (x, bar)


## Do and proc notation

description sweet unsweet
Sequencing
do putStrLn "one"
putStrLn "two"

putStrLn "one" >>
putStrLn "two"

do x <- getLine
putStrLn $"You typed: " ++ x  getLine >>= \x -> putStrLn$ "You typed: " ++ x

Let binding
do let f xs = xs ++ xs
putStrLn $f "abc"  let f xs = xs ++ xs in putStrLn$ f "abc"

Last line
do x

x


## Other constructs

description sweet unsweet
if-then-else
if x then y else z

case x of
True -> y
False -> z


## Literals

A number such as 5 in Haskell code is interpreted as fromInteger 5, where the 5 is an Integer. This allows the literal to be interpreted as Integer, Int, Float etc. Same goes with floating point numbers such as 3.3, which are interpreted as fromRational 3.3, where 3.3 is a Rational. GHC has OverloadedStrings extension, which enables the same behaviour for string types such as String and ByteString varieties from the Data.ByteString modules.

## Type level

The type [Int] is equivalent to [] Int. This makes it obvious it is an application of [] type constructor (kind * -> *) to Int (kind *).

Analogously, (Bool, String) is equivalent to (,) Bool String, and the same goes with larger tuples.