Syntactic sugar refers to any redundant type of syntax in a programming language that is redundant to the main syntax but which (hopefully) makes the code easier to understand or write.
Functions and constructors
- For more information, see the chapter More on functions
description | sweet | unsweet |
---|---|---|
infix 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 |
Function Bindings
- For more information, see the chapter Haskell/Variables_and_functions
description | sweet | unsweet |
---|---|---|
function definitions | f x y = x * y |
f = \x y -> x * yfurther desugared to f = \x -> \y -> x * y |
pattern matching | f [] = 0 f (' ':xs) = f xs f (x:xs) = 1 + f xs |
f = \l -> case l of [] -> 0 (' ':xs) -> f xs (x:xs) -> 1 + f xs |
Lists
- For more information, see the chapters Lists and tuples, Lists II, Lists III, Understanding monads/List and MonadPlus
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) |
Records
description | sweet | unsweet |
---|---|---|
Creation | data Ball = Ball { x :: Double , y :: Double , radius :: Double , mass :: Double } |
data Ball = Ball Double Double Double Double x :: Ball -> Double x (Ball x_ _ _ _) = x_ y :: Ball -> Double y (Ball _ y_ _ _) = y_ radius :: Ball -> Double radius (Ball _ _ radius_ _) = radius_ mass :: Ball -> Double mass (Ball _ _ _ mass_) = mass_ |
Pattern matching | getArea Ball {radius = r} = (r**2) * pi |
getArea (Ball _ _ r _) = (r**2) * pi |
Changing values | moveBall dx dy ball = ball {x = (x ball)+dx, y = (y ball)+dy} |
moveBall dx dy (Ball x y a m) = Ball (x+dx) (y+dy) a m |
Do notation
- For more information, see the chapters Understanding monads and do Notation.
description | sweet | unsweet |
---|---|---|
Sequencing | do putStrLn "one" putStrLn "two" |
putStrLn "one" >> putStrLn "two" |
Monadic binding | 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.
Function types have the same type of sugar: Int -> Bool
can also be written as (->) Int Bool
.
Layout
- For more information on layout, see the chapter on Indentation