Operators, sections, and fixity

Contents
Operators are functions
The common operators
Fixity and backticks
Define your own

Operators are functions

An operator is a function whose name is made of symbols. It can be used in prefix form with parentheses, and any function can be used in infix form with backticks:

2 + 3 -- 5 (+) 2 3 -- the same call 10 `div` 3 -- 3 div 10 3 -- the same call

Backticks turn a named function into an infix one, which reads better for comparisons and membership tests:

3 `elem` [1,2,3] -- True "cat" `isPrefixOf` "catalog" -- True

The common operators

Six of them cover most code you will read. The last two are the ones beginners postpone, and both are worth learning early:

++ -- concatenate two lists : -- prepend one element !! -- index into a list, partial $ -- apply, lowest precedence . -- compose two functions, right to left <$> -- fmap as an operator

. is the one to practise. It takes two functions and returns the function that applies the right one first, so f . g reads inside out.

Fixity and backticks

Every operator has a precedence from 0 to 9 and an associativity. :info prints both, and the answer explains why an expression groups the way it does:

ghci> :i (+) type Num :: * -> Constraint class Num a where (+) :: a -> a -> a ... infixl 6 + ghci> :i (:) type [] :: * -> * data [] a = [] | a : [a] infixr 5 :

infixl 6 means left associative at level 6, and infixr 5 means right associative at level 5. That is why 1 : 2 : [] needs no parentheses.

Define your own

Any function with a symbolic name can be an operator, and a fixity declaration decides how it groups. Here is a small one for building ranges of text:

(<.>) :: String -> String -> String a <.> b = a ++ "/" ++ b infixr 6 <.> -- "dev" <.> "haskell" <.> "course" -- "dev/haskell/course"

Resist inventing operators for ordinary functions. A reader parses a named function instantly and an unfamiliar symbol only after a lookup, so symbols are for the cases where infix form genuinely reads better.

Next: if, guards, and pattern guards

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

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: