mirror of
https://github.com/LeCoupa/awesome-cheatsheets.git
synced 2026-01-25 12:48:07 -08:00
Created a cheatsheet for the Haskell language.
This commit is contained in:
committed by
GitHub
parent
52d590f1c3
commit
8840648ff4
479
languages/haskell.txt
Normal file
479
languages/haskell.txt
Normal file
@@ -0,0 +1,479 @@
|
|||||||
|
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())
|
||||||
Reference in New Issue
Block a user