Files
awesome-cheatsheets/languages/haskell.txt
2019-01-18 16:48:15 +01:00

480 lines
16 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
CHEATSHEET HASKELL
Use HASKELL
Documentation
- Haskell API search: http://www.haskell.org/hoogle/
- Haskell reference: ftp://ftpdeveloppez.com/cmaneu/langages/haskell/haskellreference.zip
Basics
- Load file :load filename
- Reload file :reload
- Launch file editor with current file :edit
- Get information about a function :info command
Comments
A single line comment starts with -- and extends to the end of the line.
Multi-line comments start with {- and extend to -}. Comments can be nested.
Reserved words
!
'
''
-
--
-<
-<<
->
::
;
<-
,
=
=>
>
?
#
*
@
[|, |]
\
_
`
{, }
{-, -}
|
~
as
case, of
class
data
data family
data instance
default
deriving
deriving instance
do
forall
foreign
hiding
if, then, else
import
infix, infixl, infixr
instance
let, in
mdo
module
newtype
proc
qualified
rec
type
type family
type instance
where
Data types
All the data types must start by a capital letter.
Int: Integer number with fixed precision
Integer: Integer number with virtually no limits
Float: Real floating point with single precision
Double: Real floating point with double the precision
Bool: Boolean
Char: Character, have to placed between quotes
String: A list of Chars
Type redefinition
Type NewTypeName = TypeValue
Example: Type String = [Char]
List & Numbers
[] Empty list
[1,2,3,4] List of four numbers
1 : 2 : 3 : 4 : [] - Write a lists using cons (:) and nil ([])
[1..100] - List of number 1,2,3..,100
[100..] - Infinite list of number 100,101,102,103,..
[0,-1 ..] - Negative integers 0,-1,-2,..
(h:q) - h stands for the first element of the list and q for the result
(f:s:t:q) - f is the first element, s is the second elemnt, t is the third and q is the rest of the elements of the list.
It can be added the element e to the list l with e:l
Basic functions for lists
list1++list2 append two list
list!!n return element n
head takes a list and returns its head. The head of a list is basically its first element.
tail takes a list and returns its tail. In other words, it chops off a list's head.
last takes a list and returns its last element.
init takes a list and returns everything except its last element.
length takes a list and returns its length, obviously.
null checks if a list is empty.
reverse reverses a list.
take takes number and a list. It extracts that many elements from the beginning of the list.
drop works in a similar way as take, only it drops the number of elements from the beginning of a list.
maximum takes a list of stuff that can be put in some kind of order and returns the biggest element.
minimum returns the smallest.
sum takes a list of numbers and returns their sum.
product takes a list of numbers and returns their product.
elem takes a thing and a list of things and tells us if that thing is an element of the list. It's usually called as an infix function because it's easier to read that way.
Function for infinite lists:
cycle: takes a list and cycles it into an infinite list. If you just try to display the result, it will go on forever so you have to slice it off somewhere.
repeat: takes an element and produces an infinite list of just that element. It's like cycling a list with only one element.
replicate: takes the number of the same element in a list.
List comprehension
List comprehension is the process of generating a list using a mathematical expression.
[body | generator]
Examples: [x*a | a <- [1..3]] = [2,4,6]
[x*y | x <- [1..5], y <- [9..5] ]
[x | x <- [1,10,14,16,18], x>5 ]
Tuples
(1,"a") - 2-element tuple of a number and a string
(last, 4, 'b') - 3-element tuple of a function, a number and a character
Note that the empty tuple () is also a type which can only have a single value: ()
Basic functions for Tuples
fst: takes a pair and returns its first component.
snd: takes a pair and returns its second component.
zip: takes two lists and then zips them together into one list by joining the matching elements into pairs.
Note: these functions operate only on pairs. They won't work on triples, 4-tuples, 5-tuples, etc.
Typeclasses
A typeclass is a sort of interface that defines some behaviour.
If a type is a part of a typeclass, that means that it supports and implements the behavior the typeclass describes.
If you come from OPP you can think of them kind of as Java interfaces, only better.
Everything before the => symbol is called a class constraint.
Eq is used for types that support equality testing. Eq class constraint for a type variable in a function, it uses == or /= somewhere inside its definition
Ord is for types that have an ordering. Ord covers all the standard comparing functions such as >, <, >= and <=
Show can be presented as strings. show takes a value whose type is a member of Show and presents it to us as a string.
Read is sort of the opposite typeclass of Show. The read function takes a string and returns a type which is a member of Read.
Enum members are sequentially ordered types, they can be enumerated. Types in this class: (), Bool, Char, Ordering, Int, Integer, Float and Double.
Bounded members have an upper and a lower bound. All tuples are part of Bounded. Types in this class: Bool, Int and Char.
Num is a numeric typeclass. Types in this class: Int, Integer, Float and Double.
Integral is also a numeric typeclass. In this typeclass are Int and Integer.
Floating includes only floating point numbers. Types in this class: Float and Double.
Functions
Functions are defined by declaring their name, any arguments, and an equals sign.
Declare a new function starting with explicit type declaration (optional)
functionName :: inpuntType1 [ -> inputTypeN ] -> outputType
Declare a new function with pattern matching
intToChar 1 = "One"
intToChar 2 = "Two"
Declare a new function with guards
intToChar x
| x==1 = "One"
| x==2 = "Two"
Declare a new function with guards and pattern matching
allEmpty _ = falsePart
allEmpty [] = truePart
alwaysEven n
| otherwise = False
| n 'div' 2 == 0 = True
Declare a new function with record syntax
Being this data type:
data Color = C { red,
, blue
, yellow :: Int }
It can only be match on blue only:
isBlueZero (C { blue = 0 }) = True
isBlueZero _ = False
Defining a PixelColor type and a function replace values with non-zero blue components.
Where and let
Let must always be followed by in. The in must appear in the sale column as the let keyword.
In the following example, mult multiples its argument n by x, which passed to the original multiples.
multiples x =
let mult n = n * x
in map mult [1..10]
Where is similar to let. The scope of a where definition is the current function.
In the following example, the function result below has a different meaning depending on the arguments given to the function strlen:
strlen [] = result
where result = "No string given!"
strlen f = result ++ " characters long!"
where result = show (length f)
It is important to know that let ... in ... is an expression, that is, it can be written wherever expressions are allowed.
In contrast, where is bound to a surrounding syntactic construct, like the pattern matching line of a function definition.
Advantage of where
Suppose you have the function
f :: s -> (a,s)
f x = y
where y = ... x ...
and later you decide to put this into the Control.Monad.State monad.
However, transforming to
f :: State s a
f = State $ \x -> y
where y = ... x ...
will not work, because where refers to the pattern matching f =, where no x is in scope. In contrast, if you had started with let, then you wouldn't have trouble.
f :: s -> (a,s)
f x =
let y = ... x ...
in y
This is easily transformed to:
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
Advantage of let
Because "where" blocks are bound to a syntactic construct, they can be used to share bindings between parts of a function that are not syntactically expressions.
For example:
f x
| cond1 x = a
| cond2 x = g a
| otherwise = f (h x a)
where
a = w x
In expression style, you might use an explicit case:
f x
= let a = w x
in case () of
_ | cond1 x -> a
| cond2 x -> g a
| otherwise -> f (h x a)
or a functional equivalent:
f x =
let a = w x
in select (f (h x a))
[(cond1 x, a),
(cond2 x, g a)]
or a series of if-then-else expressions:
f x
= let a = w x
in if cond1 x
then a
else if cond2 x
then g a
Anonymous Functions
They are functions without names and can be defined at any time like so.
Example: \x -> x + 1
Case expressions
case is to a switch statement in C# and Java. However, it can match a pattern.
Example:
data Choices = First String | Second | Third | Fourth
case can be used to determine which choice was given
whichChoice ch =
case ch of
First _ -> "1st!"
Second -> "2nd!"
_ -> "Something else."
Conditionals
Identify ==
Non identify /n
Comparatives where the type must a subclass of Ord <,>,<=,>=
The if statement has this “signature”: if-then-else :: Bool -> a -> a -> a
Maps and filters
map takes a function and a list and applies that function to every element in the list, producing a new list.
Examples:
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
filter is a function that takes a predicate and nd a list and then returns the list of elements that satisfy the predicate
Examples:
filter :: (a -> Bool) -> [a] -> [a]
filter _ [] = []
filter p (x:xs)
| p x = x : filter p xs
| otherwise = filter p xs
Folds
foldl function folds the list up from the left side.
foldr works in a similar way to the left fold, only the accumulator eats up the values from the right.
The foldl1 and foldr1 functions work much like foldl and foldr, only you don't need to provide them with an explicit starting value.
scanl and scanr are like foldl and foldr, only they report all the intermediate accumulator states in the form of a list.
Function application with $
The $ function has the lowest precedence and the function with $ is rigth-associate
Default
Default implementations can be given for function in a class.
The default is defined by giving a body to one of the members' functions.
Example == can be defined in terms of /=:
(==) a b = not (a/b)
Data
Algebraic data types can be declared as: data MyType = MyValue1 | MyValue2
Note that type and constructor names must start with a capital letter. It is a syntax error otherwise.
Constructors with arguments
Constructors that take arguments can be declared, allowing more information to be stored.
data Point = TwoD Int Int
| ThreeD Int Int Int
Notice that the arguments for each constructor are type names, not constructors.
Type and constructor names
Both names can be the same since they will never be used in a place that would cause confusion.
data User = User String | Admin String
Using this type in a function makes difference clear:
whatUser (User _) = "normal user"
whatUser (Admin _) = "admin user"
Type Variables
Plymorphic data types are easy to be declared just by adding type varialbe in the declaration:
data Slot a = Slot1 a | Empty1
It can also be mix type variable and specific types in constructors:
data Slot2 a = Slot2 a Int | Empty2
Record syntax
Constructors arguments can also be declared by using record syntax which gives a name to each argument.
For example:
data Contact = Contact { ctName :: String
, ctEmail :: String
, ctPhone :: String }
Note: Multiple constructors of the same type can use the same accessor function name for values of the same type.
Deriving
The capabilities to convert to and from strings, compare
for equality, or order in a sequence are defined as Typeclasses and Haskell provides the deriving keyboard to automatically implement the typeclass on the associated type supported which are: Eq, Read, Show, Ord, Enum, Ix, and
Bounded.
Two forms of deriving are possible.
The first is used when a type only derives one class:
data Priority = Low | Medium | High
deriving Show
The second is used when multiple classes are derived:
data Alarm = Soft | Loud | Deafening
deriving (Read, Show)
Class constraint
In any case, the syntax used is:
data (Num a) => SomeNumber a = Two a a
| Three a a a
This declares a type SomeNumber which has one type variable argument.
Valid types are those in the Num class.
Do
Do indicates that the code to follow will be in a monadic context.
Statements are separated by newlines, the assignment is indicated by <, and a let form is introduced which does not require the in the keyboard.
If, Then, Else
This function tests if the string is given starts with a lower case letter and, if so, convert it to upper case:
sentenceCase (s:rest) =
if isLower s
then toUpper s : rest
else s : result
sentenceCase _ = []
Deconstruction
The left-hand side of a let definition can also destructive its argument, in case sub-components are to be accessed.
Examples:
firstThree str =
let (a:b:c:_) = str
in "Initial three characters are: " ++
show a ++ ", " ++
show b ++ ", and " ++
show c
Note that this is different than the following, which only works if the string has exactly three characters:
onlyThree str =
let (a:b:c:[]) = str
in "The characters given are: " ++
show a ++ ", " ++
show b ++ ", and " ++
show c
Modules
A module is a compilation unit which export functions, tyñes, classes, instances, and other modules.
To make a Haskell file a module just add at the top of it:
module MyModule where
Imports
To import everything (functions, data types and constructors, class declarations, and even other modules imported) exported by a library, just use the module name:
import Text.Read
To import selectively:
import Text.Read (readParen, lex)
To import data types and no constructors:
import Text.Read (Lexeme)
To import data types and one or more constructors explicitly
import Text.Read (Lexeme(Ident, Symbol))
To import all constructors for a given type:
import Text.Read (Lexeme())