An advanced, purely functional programming language
TODO
-
hackage.haskell.org/package/data-aviary-0.4.0/docs/Data-Aviary-Birds.html
-
stackoverflow.com/questions/39628091/defining-a-function-for-multiple-types
-
Record pattern matching e.g.
f P{name=n} = n
-
zvon.org/other/haskell/Outputsyntax/caseQexpressions_reference.html
-
learnyouahaskell.com/higher-order-functions#function-application
-
hackage.haskell.org/package/constraints-0.13.4/docs/Data-Constraint.html
-
Guards
|
-
Apostrophe in names
-
hackage.haskell.org/package/probability-0.2.8/docs/Numeric-Probability-Distribution.html
-
www.schoolofhaskell.com/school/starting-with-haskell/basics-of-haskell/13-the-list-monad
-
www.adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
-
downloads.haskell.org/~ghc/8.6.5/docs/html/users_guide/ghci.html#the-ghci-debugger
-
ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/pattern_synonyms.html
References
-
[haskell-wikibook] Haskell by en.wikibooks.org
-
[a-gentle-introduction-to-haskell] A Gentle Introduction To Haskell by Paul Hudak, John Peterson, Joseph Fasel
-
[haskell-2010] Haskell 2010 Language Report
-
[haskell-98] Haskell 98 Language and Libraries The Revised Report December 2002
-
[a-history-of-haskell] A History of Haskell: Being Lazy With Class
-
[learn-you-a-haskell] Learn You a Haskell for Great Good! A Beginner’s Guide by Miran Lipovača
-
[cheatsheet] Haskell Cheat Sheet
-
Introduction to Haskell (Spring 2013) by Brent Yorgey at University of Pennsylvania
Basics
So far, if I could pick just one resource from which to learn Haskell, it would be the [haskell-wikibook].
$ curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
$ ghci
ghci> -- Double dash makes comment up to the end of the line.
Evaluation of Expressions
Because Haskell is a purely functional language, all computations are done via the evaluation of expressions (syntactic terms) to yield values
chapter 2 Values, Types, and Other Goodies
False
yields boolean value False
.ghci> False
False
[]
yields empty list []
.ghci> []
[]
[ False , True ]
yields list [False,True]
.ghci> [ False , True ]
[False,True]
Types
- NOTE
-
:type
is one of GHCi commands.
False
has type (::
) boolean type (Bool
).ghci> :type False
False :: Bool
[]
) has type (::
) list of type a
([a]
).ghci> :type []
[] :: [a]
False
value ([False]
) has type (::
) list of booleans ([Bool]
).ghci> :type [False]
[False] :: [Bool]
0
) has type (::
) type a
constrained (=>
) to be instance of class Num (Num a
).ghci> :type 0
0 :: Num a => a
[1,2,3]
) has type (::
) list of type a
([a]
) constrained (=>
) to be instance of class Num (Num a
).ghci> :type [1,2,3]
[1,2,3] :: Num a => [a]
ghci> :kind Bool
Bool :: *
ghci> :kind [Bool]
[Bool] :: *
ghci> :kind [] Bool
[] Bool :: *
ghci> :kind (Bool -> Bool)
(Bool -> Bool) :: *
ghci> :kind (->) Bool Bool
(->) Bool Bool :: *
ghci> :kind []
[] :: * -> *
ghci> :kind (->) Bool
(->) Bool :: * -> *
ghci> :kind (->)
(->) :: * -> * -> *
Lazy Evaluation
ghci> [1..10]
[1,2,3,4,5,6,7,8,9,10]
ghci> take 10 [1..]
[1,2,3,4,5,6,7,8,9,10]
Because Haskell is lazy, it won’t try to evaluate the infinite list immediately because it would never finish. It’ll wait to see what you want to get out of that infinite lists.
Function Application
Function application is denoted by juxtaposition and associates to the left. Thus,f x y
is parsed(f x) y
.
ghci> take 10 [1..]
[1,2,3,4,5,6,7,8,9,10]
ghci>
ghci> (take 10) [1..]
[1,2,3,4,5,6,7,8,9,10]
Function Type
not
has type (::
) applied to boolean (Bool
) returns (->
) boolean (Bool
).ghci> :type not
not :: Bool -> Bool
not
applied to value True
returns False
.ghci> not True
False
Currying
a function of two arguments may be represented as a function of one argument that itself returns a function of one argument.
take
has type (::
) applied to Int
returns (->
) function with type [a] -> [a]
.ghci> :type take
take :: Int -> [a] -> [a]
takeFirst10
by application of function take
to the number 10
.ghci> takeFirst10 = take 10
ghci> :type takeFirst10
takeFirst10 :: [a] -> [a]
ghci>
ghci> takeFirst10 [1..]
[1,2,3,4,5,6,7,8,9,10]
Infix Operators
[Lexically, infix operators consist entirely of "symbols," as opposed to normal identifiers which are alphanumeric (§2.4). Haskell has no prefix operators, with the exception of minus (-), which is both infix and prefix.]
chapter 3 Functions
ghci> 0 - 1
-1
ghci> 10 ^ 2
100
ghci> 0 : []
[0]
ghci> 1 : 0 : []
[1,0]
ghci> [0] ++ [1]
[0,1]
ghci> ['a'..] !! 9
'j'
A section is a partial application of an infix operator to no arguments, the left argument, or the right argument—and by surrounding the result in parentheses
ghci> power = (^)
ghci> 2 `power` 3
8
ghci> power 2 3
8
ghci>
ghci> cube = (^3)
ghci> cube 2
8
ghci>
ghci> powerOf2 = (2^)
ghci> powerOf2 3
8
- WARNING
-
(-42)
equals to-42
not to a function that subtracts42
. In order to get the later, write(subtract 42)
There are very few predefined “operators” in Haskell - most that do look predefined are actually syntax (e.g., “=”). Instead, operators are simply functions that take two arguments and have special syntax support.
Allowable symbols which can be used to define operators are:
# $ % & * + . / < = > ? @ \ ^ | - ~However, there are several “operators” which cannot be redefined. They are:
<-
,->
and=
. The last,=
, cannot be redefined by itself, but can be used as part of multi-character operator.
Precedence and Associativity
A fixity declaration can be given for any infix operator or constructor (including those made from ordinary identifiers, such as elem
). This declaration specifies a precedence level from 0 to 9 (with 9 being the strongest; normal application is assumed to have a precedence level of 10), and left-, right-, or non-associativity.
chapter 3 Functions
If no fixity declaration is given for a particular operator, it defaults to infixl 9.
chapter 3 Functions
:info
command in ghci.ghci> :info /
type Fractional :: * -> Constraint
class Num a => Fractional a where
(/) :: a -> a -> a
...
-- Defined in ‘GHC.Real’
infixl 7 /
Fixity infixl 7 /
means infix operator, left associativity, precedence 7.
ghci> 1 / 2 / 3
0.16666666666666666
ghci> (1 / 2) / 3
0.16666666666666666
ghci> 1 * 2 / 3
0.6666666666666666
ghci> 3 ^ 2 ^ 1 ^ 0
9
ghci> 3 ^ (2 ^ (1 ^ 0))
9
ghci> ((3 ^ 2) ^ 1) ^ 0
1
///
with right associativity in file RightDivision.hs
module RightDivision ((///)) where
infixr 7 ///
(///) :: Fractional a => a -> a -> a
a /// b = a / b
///
operator.ghci> :load RightDivision
[1 of 1] Compiling RightDivision ( RightDivision.hs, interpreted )
Ok, one module loaded.
ghci> 1 /// 2 /// 3
1.5
ghci> 1 /// 2 * 3
<interactive>:6:1: error:
Precedence parsing error
cannot mix ‘///’ [infixr 7] and ‘*’ [infixl 7] in the same infix expression
Modules
A Haskell program is a collection of modules, one of which, by convention, must be called Main and must export the value main.
A module begins with a header: the keyword module, the module name, and a list of entities (enclosed in round parentheses) to be exported. The header is followed by a possibly-empty list of import declarations (impdecls, Section 5.3) that specify modules to be imported, optionally restricting the imported bindings. This is followed by a possibly-empty list of top-level declarations (topdecls, Chapter 4).
Example of module Main header
Main
, which exports function main
.module Main(main) where
This exact header is inserted as a first line, if other header is omitted.
For more information, see en.wikibooks.org/wiki/Haskell/Modules.
base: Basic libraries
This package contains the Standard Haskell Prelude and its support libraries, and a large collection of useful libraries ranging from data structures to parsing combinators and debugging utilities.
Prelude
There is one distinguished module, Prelude, which is imported into all modules by default
Simple combinators working solely on and with functions.
-
Identity function
id
-
Constant function
const
-
Function composition.
(.)
-
Flip function
flip
-
Function application operator
($)
-
Reverse application operator
(&)
-
fix
is the least defined x such that f x = x -
on b u x y
runs the binary function b on the results of applying unary function u to two arguments x and y.
To understand fix
I recommend reading en.wikibooks.org/wiki/Haskell/Fix_and_recursion and en.wikibooks.org/wiki/Haskell/Denotational_semantics.
fmap
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
(>>=)
class Applicative m => Monad m where
(>>=) :: forall a b. m a -> (a -> m b) -> m b
Do Expressions
A do expression provides a more conventional syntax for monadic programming. It allows an expression such as
putStr "x: " >> getLine >>= \l -> return (words l)to be written in a more traditional way as:
do putStr "x: " l <- getLine return (words l)
3.14 Do Expressions
ap :: (Monad m) => m (a -> b) -> m a -> m b
ap m1 m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }
(<>) | sconcat
class Semigroup a where
(<>) :: a -> a -> a
mempty | mconcat
class Semigroup a => Monoid a where
mempty :: a
foldMap | foldr
class Foldable t where
foldMap :: Monoid m => (a -> m) -> t a -> m
traverse | sequenceA
class (Functor t, Foldable t) => Traversable t where
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
Packages
Hackage is the Haskell community’s central package archive of open source software. Hackage has been online since January 2007 and is constantly growing.
- containers: Assorted concrete container types
-
This package contains efficient general-purpose implementations of various immutable container types including sets, maps, sequences, trees, and graphs.
- safe: Library of safe (exception free) functions
-
A library wrapping Prelude/Data.List functions that can throw exceptions, such as head and !!. Each unsafe function has up to four variants
- lens: Lenses, Folds and Traversals
-
The combinators in Control.Lens provide a highly generic toolbox for composing families of getters, folds, isomorphisms, traversals, setters and lenses and their indexed variants.
- repa: High performance, regular, shape polymorphic parallel arrays.
-
Repa provides high performance, regular, multi-dimensional, shape polymorphic parallel arrays.
- array: Mutable and immutable arrays
-
In addition to providing the Data.Array module as specified in the Haskell 2010 Language Report, this package also defines the classes IArray of immutable arrays and MArray of arrays mutable within appropriate monads, as well as some instances of these classes.