123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676 |
- Haskell reference
- Haskell is a functional (that is, everything is done with function calls),
- statically, implicitly typed (types are checked by the compiler, but you don't
- have to declare them), lazy (nothing is done until it needs to be) language.
- www.haskell.org/platform/
- www.haskell.org/downloads/
- www.haskell.org/hoogle/
- For beginners - https://argumatronic.com/posts/1970-01-01-beginners.html
- Documentation:
- Haskell Documentation - https://haskell.org/
- Haskell Tutorials - https://wiki.haskell.org/Tutorials
- Haskell in 5 steps - https://wiki.haskell.org/Haskell_in_5_steps
- Haskell Books and tutorials - https://wiki.haskell.org/Books_and_tutorials
- Cabal User Guide - https://cabal.readthedocs.io/en/stable/
- Haskell Cabal (Common Architecture for Building Applications and Libraries) -
- https://www.haskell.org/cabal/index.html#nstall-upgrade
- Basic libraries -
- https://hackage.haskell.org/package/base-4.17.0.0/docs/Data-List.html
- Math functions -
- https://hackage.haskell.org/package/ClassyPrelude-0.1/docs/Prelude-Math.html
- Collection of tools for numeric computations -
- https://hackage.haskell.org/package/math-functions
- Introduction to Haskell -
- https://www.cis.upenn.edu/~cis1940/spring13/lectures.html
- Haskell and Functional Programming -
- https://courses.cs.washington.edu/courses/cse341/14wi/haskell/index.html
- Glasgow Haskell Compiler -
- https://downloads.haskell.org/ghc/latest/docs/users_guide/index.html
- Learn you a haskell for great good - http://learnyouhaskell.com/
- FP Complete Haskell - https://www.fpcomplete.com/haskell/learn/
- Applied Haskell Syllabus - https://www.fpcomplete.com/haskell/syllabus/
- Haskell for python developers -
- https://www.softwarefactory-project.io/haskell-for-python-developers.html
- Installation: https://www.haskell.org/ghcup/install/
- $ curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
- System requirements [Linux Debian]
- build-essential
- curl
- libffi-dev
- libffi6
- libgmp-dev
- libgmp10
- libncurses-dev
- libncurses5
- libtinfo5
- ghcup user guide: https://www.haskell.org/ghcup/guide/
- ghcup tui # text-based user interface
- ghcup --help # help
- ghcup list # list available ghc/cabal versions
- ghcup install ghc # install the recommended GHC version
- ghcup install ghc 8.2.2 # install a specific GHC version
- ghcup set ghc 8.4.4 # set the currently "active" GHC version
- ghcup install cabal # install cabal install
- ghcup upgrade # update ghcup itself
- ghc -- compiles Haskell libraries or applications to binary code
- ghci -- an interpreter that lets you write Haskell code and get feedback
- -- compile haskell program
- $ ghc -o program program.hs
- -- alternatively, we can skip the compilation phase
- -- runghc interprets the source file instead of compiling it
- $ runghc program.hs
- -- -Wall flag will enable GHC to emit warnings about our code
- $ ghc -Wall program.hs -fforce-recomp
- -- build with ghc
- $ ghc --make program.hs
- -- essential commands
- :? -- list commands (show all commands)
- :quit (or :q)
- :load filename.hs (or :l filename.hs)
- :reload -- reload the current file set after you'ved edited it (or :r)
- :set editor name -- set editor to "name"
- :edit name -- edit current script
- :cd -- change to another directory
- :type expr -- give the type of an expression (or -- just :t)
- :set +t tell Haskell to print type information after evaluation
- :kind (or :k) -- kind inspection
- :info (or :i) -- information
- :print (or :p) -- print the expression
- :module (or :m) -- add modules to imports
- :add (or :ad) -- load a file into the REPL namespace
- :instances (or :in) -- show instances of a typeclass
- :browse (or :bro) -- browse all available symbols in the REPL namespace
- -- The major namespaces are described below with their naming conventions
- Namespace Convention
- Modules Uppercase
- Functions Lowercase
- Variables Lowercase
- Type Variables Lowercase
- Datatypes Uppercase
- Constructors Uppercase
- Typeclasses Uppercase
- Synonyms Uppercase
- Type Families Uppercase
- -- the following list of keywords have a special meaning in the language, and
- -- cannot be used as the names of functions or their arguments:
- case class data default deriving
- do else foreign if import in
- infix infixl infixr instance let
- module newtype of then type where
- -- some basic types in Haskell
- Type Name Example value
- Integers (limited range) Int 42
- Integers (infinite range) Integer 7376541234
- Reals Float 3.1415927
- Booleans Bool False
- Characters Char 'a'
- Strings String "haskell"
- -- some basic operations in Haskell
- Name Operation
- a == b Equality (a = b)
- a /= b Inequality (a != b)
- a && b Logical and (a ^ b)
- a || b Logical or (a v b)
- logBase b x Logarithm (log_b x)
- truncate x select integer part only
- -- differences between function application in mathematics and in Haskell
- Mathematics Haskell
- f(x) f x
- f(x, y) f x y
- f(g(x)) f (g x)
- f(x, g(y)) f x (g y)
- f(x) g(y) f x * g y
- -- single line comments are made with double dashes
- {- multi-line comment made
- with braces and dashes
- -}
- -- executing the program in ghci
- ghci> :l program.hs (:load)
- ghci> :r (:reload)
- -- standard prelude
- -- select the first element of a non-empty list
- > head [1, 2, 3, 4, 5]
- 1
- -- remove the first element from a non-empty list
- > tail [1, 2, 3, 4, 5]
- [2, 3, 4, 5]
- -- select the nth element of list (counting from zero)
- > [1, 2, 3, 4, 5] !! 2
- 3
- -- select the first n elements of a list
- > take 3 [1, 2, 3, 4, 5]
- [1, 2, 3]
- -- remove the first n elements from a list
- > drop 3 [1, 2, 3, 4, 5]
- [4, 5]
- -- calculate the length of a list
- > length [1, 2, 3, 4, 5]
- 5
- -- calculate the sum of a list of numbers
- > sum [1, 2, 3, 4, 5]
- 15
- -- calculate the product of a list of numbers
- > product [1, 2, 3, 4, 5]
- 120
- -- append two lists
- > [1, 2, 3] ++ [4, 5]
- [1, 2, 3, 4, 5]
- -- reverse a list
- > reverse [1, 2, 3, 4, 5]
- [5, 4, 3, 2, 1]
- -- defining functions
- -- let functionName argName
- ghci> let addOneTo i = i + 1 -- in this case the argument is i
- ghci> addOneTo 5
- 6
- -- factorial function
- factorial :: Int -> Int
- factorial n = if n == 0 then 1 else n * factorial(n - 1)
- -- factorial computation without the above function
- factorial n = product [1..n]
- -- fibonacci function
- fibonacci :: Int -> Int
- fibonacci n = if n == 0 then 0 else if n == 1 then 1 else fibonacci(n - 2) + fibonacci(n - 1)
- -- nested function using let
- -- function that takes two numbers and outputs two numbers
- alwaysEven a b = let isEven x = if even x
- then x
- else x - 1
- in (isEven a, isEven b)
- -- in can be written anywhere as long as it is written after the let functions
- ghci> alwaysEven 30 23
- (30,22)
- ghci> isEven 5
- <interactive> Not in scope 'isEven'
- -- nested function using where
- -- function that takes two numbers and outputs two numbers
- alwaysEven a b = (isEven a, isEven b)
- where isEven x = if even x then x else x - 1
- -- equality checks
- ghci> 1 /= 2 -- in almost other programming languages 1 != 2
- True
- ghci> 1 == 1
- True
- -- function names
- function123 -- correct
- fUNCTION123 -- correct
- function' -- correct
- Function -- incorrect
- 123function -- incorrect
- 'function -- incorrect
- -- infix functions: functions that take argument on the left and an argument on the right
- a + b
- a - b
- a * b
- a / b
- a ^ b
- a == b
- a /= b
- -- prefix functions: two arguments on the right
- even a
- max a b
- min a b
- -- infix functions can also be used as prefix functions when wraped in parentheses
- (+) 1 2
- -- prefix functions are also be used as infix functions
- a `max` b
- a `min` b
- --lists and tuples are used to store multiple items
- -- list: can store anything with single type (list of ints, list of characters)
- same = ['l', 'c'] == "lc"
- -- head: changes its type from list of int to int
- head :: [a] -> a
- head [1, 2, 3]
- 1
- head "Institute"
- 'I'
- -- tail
- tail :: [a] -> [a]
- tail [1, 2, 3]
- [2, 3]
- tail "Institute"
- "nstitute"
- -- last
- last :: [a] -> a
- last [1, 2, 3]
- 3
- last "Institute"
- 'e'
- -- init
- init :: [a] -> [a]
- init [1, 2, 3]
- [1, 2]
- init "Institute"
- "Institut"
- -- list of lists (nested list)
- -- the nested list are seen as single values just like characters or ints in a list
- let ourList = [[1, 2, 3], [4, 5, 6]]
- ourList
- [[1, 2, 3], [4, 5, 6]]
- head ourList
- [1,2,3]
- tail ourList
- [[4,5,6]]
- last ourList
- [4,5,6]
- init ourList
- [[1,2,3]]
- -- get certain element from the list
- [1, 2, 3, 4, 5, 6] !! 2
- 3 -- index starts from 0
- -- add values to a list
- : is an infix function that takes single value on its left and a list on its right
- 1 : [2, 3, 4, 5, 6] -- which are of same type (prepending function)
- [1,2,3,4,5,6]
- ++ is also an infix function which appends a list to another list which are of same type
- [1, 2, 3] ++ [4, 5, 6]
- [1,2,3,4,5,6]
- -- the function to append list however is slower than the prepending function
- -- this because when we prepend a value to a list it will be added almost instantly
- -- however when we append a values the program has to go all the way to the end of the
- -- list to append it and when dealing with large list this can become quite slow
- -- haskell doesn't know where the end of the list is, it only knows what the first item is
- -- so it has to check all the items before it can get to the end
- -- laziness
- -- simply put haskell only evaluates something if it is asked for, the cool thing about
- -- that is when we need to get the first item of the list it wont bother with the rest of
- -- it, it will evaluate the first item and nothing more, this is great in terms of
- -- performance, and enable us to create interesting algorithms
- ghci> ourList = [1, 2, 3, error "Whoops", 5, 6, 7]
- ghci> ourList
- [1,2,3,*** Exception: Whoops
- ghci> take 3 ourList
- [1,2,3]
- ghci> drop 4 ourList
- [5,6,7]
- ghci> drop 3 ourList
- [*** Exception: Whoops
- -- this proves that whenever we ask for specific thing in haskell we truely only get that
- -- and nothing more
- -- range
- ghci> [1..10]
- [1,2,3,4,5,6,7,8,9,10]
- ghci> [0,2..10]
- [0,2,4,6,8,10]
- ghci> [1..] -- infinite list
- ghci> take 3 (drop 5 [1..])
- [6,7,8]
- -- tuples
- -- tuples are quite different from the lists and used for different purposes
- -- they can carry multiple types in a single tuple whereas list can hold only one type
- ghci> person = (22, "Kevin") -- (id, "name")
- -- all the functions that we learned for list cannot be applied for tuples
- ghci> fst person
- 22
- ghci> snd person
- "Kevin"
- -- these functions only work on the tuples of size 2
- -- we can make tuples as large as 15 values but if we are creating a 15 value tuple then
- -- the chances are there is better solutions to the problem
- -- list of tuples
- personList = [(22, "Kevin"), (35, "Zach"), (38, "Aiden")] -- database of users with id and name
- ghci> lookup 35 personList
- Just "Zach"
- ghci> lookup 8 personList
- Nothing
- -- zip two list together to form a list of tuples
- ghci> zip [1,2,3] ["yes","no","maybe"]
- [(1,"yes"),(2,"no"),(3,"maybe")]
- ghci> [1,2,3] `zip` ["yes","no","maybe"]
- [(1,"yes"),(2,"no"),(3,"maybe")]
- -- on a final note when we create a list of tuples every tuple must contain a same types
- -- or else it wont work, differently constructed tuples are seen as different types
- [(Int, String)] -- [(1, "yes"),(2, "no")] - Correct
- [(String, Int)] -- [("no", 2),("yes", 1)] - Correct
- -- calling functions is done by putting the arguments directly after the
- function. There are no parenthesies as part of the function call:
- > succ 5
- 6
- > truncate 6.59
- 6
- > round 6.59
- 7
- > sqrt 2
- 1.4142135623730951
- > not (5 < 3)
- True
- > gcd 21 14
- 7
- -- I/O actions can be used to read from and write to the console.
- > putStrLn "The quick brown fox jumps over the lazy dog"
- The quick brown fox jumps over the lazy dog
- > putStr "No newline"
- No newline>
- > print (5 + 4)
- 9
- > print (1 < 2)
- True
- -- The putStr and putStrLn functions output strings to the terminal. The print
- function outputs any type of value. (If you print a string, it will have quotes
- around it.)
- -- If you need multiple I/O actions in one expression, you can use a do block.
- Actions are separated by semicolons.
- > do { putStr "2 + 2 =" ; print (2 + 2) }
- 2 + 2 = 4
- > do { putStrLn "ABCDE" ; putStrLn "12345" }
- ABCDE
- 12345
- -- Reading can be done with getLine (which gives back a String) or readLn (which
- gives back whatever type of value you want). The <- symbol is used to assign a
- name to the result of an I/O action.
- > do { n <- readLn ; print (n^2) }
- 4
- 16
- (The 4 was input. The 16 was a result.)
- -- There is actually another way to write do blocks. If you leave off the braces
- and semicolons, then indentation becomes significant. This doesn't work so well
- in ghci, but try putting the file in a source file (say, program.hs) and build
- it.
- main = do putStrLn "What is 2 + 2?"
- x <- readLn
- if x == 4
- then putStrLn "You're right!"
- else putStrLn "You're wrong!"
- -- You can build with ghc --make program.hs, and the result will be called
- program.
- -- Haskell Tutorial
- -- An Introduction to Haskell from a non-programmer
- -- DistroTube
- -- Single line comments are made with double dashes
- {- Multi-line comment made with braces and dashes.
- - Here is the second.
- - And a third !
- -}
- -- Haskell is a functional programming language.
- -- Everything is immutable so you cannot change it!
- -- Haskell is lazy which means it only executes something when it needs to.
- -- Documentation:
- -- http://learnyouahaskell.com/
- -- https://haskell.org
- -- :l file.hs (to load file.hs in ghci)
- -- :r reload (to reload file.hs in ghci)
- -- :t variabelName (to find the type of variableName)
- -- :!clear (to run built-in shell command from ghci)
- -- :q (to quit the ghci)
- -- Imports
- import Data.List
- -- There are five numeric types in the Haskell "prelude" (the part of the
- library you get without having to import anything):
- Int is an integer with at least 30 bits of precision
- Integer is an integer with unlimited precision
- Float is a single precision floating point number
- Double is a double precision floating point number
- Rational is a fraction type, with no rounding error
- -- All five are instances of the Num type class. The first two are instances of
- Integral, and the last three are instances of Fractional.
- -- Types
- -- Bool, Int, Integer, Float, Double, Char, [Char], Tuples ()
- -- :: Bool
- -- True or False
- trueAndFalse = True && False
- trueOrFalse = True || False
- notTrue = not(True)
- boolFive = 5 > 4
- -- :: Int
- -- Whole number: from -2^63 to 2^63
- maxInt = maxBound :: Int
- minInt = minBound :: Int
- -- :: Integer
- -- Unbounded whole number
- numFive :: Integer
- numFive = 5
- -- :: Float
- numFive' = 5.0 :: Float
- myFloat :: Float
- myFloat = 1.0 + 2.5
- -- :: Double
- -- default floating point number in Haskell is Double
- -- eleven point precision
- myFloat' = 1.0 + 2.5
- myDouble = 1.55555555555 + 0.00000000001
- -- :: Char
- -- Char are single characters and denoted within single quotes
- singleChar = 'a'
- myName :: [Char]
- myName = "Saran"
- myName' = ['S', 'a', 'r', 'a', 'n'] -- same as the above
- -- Math
- addNum = 3 + 6
- subNum = 3 - 6
- mulNum = 3 * 6
- divNum = 3 / 6
- modNum = mod 9 2 -- prefix operator
- modNum' = 9 `mod` 2 -- infix operator
- addNeg = 4 + (-4)
- -- pi, exp, log, sin, cos, tan, asin, acos, atan
- truncNumber = truncate myDouble -- truncating the number 1.55555555556 to 1
- roundNumber = round myDouble -- rounding the number 1.55555555556 to 2
- ceilNumber' = ceiling myDouble -- ceiling the number 1.55555555556 to 2
- floorNumber = floor myDouble -- flooring the number 1.55555555556 to 1
- -- sqrt :: Floating a => a -> a
- sqrtFive = sqrt numFive'
- -- Lists
- numList = [1,2,3,4,5]
- numList' = [1..5] -- range of numbers
- alphaList = ['a'..'z']
- evenNum = [2,4..20]
- oddNum' = [1,3..20]
- oddAlpha' = ['a','c'..'z']
- evenAlpha = ['b','d'..'z']
- sumNumList = sum [1..5]
- sumNumList' = sum numList
- prodNumList = product [1..5]
- prodNumList' = product numList
- elemList = elem 5 numList -- is element 5 part of numList
- elemList' = 5 `elem` numList
- fibNum1 = [0,1,1,2,3,5,8]
- fibNum2 = [13,21,34,55,89,144]
- fibNum' = fibNum1 ++ fibNum2
- maxFib = maximum fibNum'
- minFib = minimum fibNum'
- listOfList = [fibNum1, fibNum2]
- addListNum = zipWith (+) [1,2,3,4,5] [6,7,8,9,10]
- addFibList = zipWith (+) fibNum1 fibNum2
- infiniteNumList = [1,2..]
- notInfinite = take 20 infiniteNumList
- infiniteFive = repeat 5
- notInfiniteFive = take 20 infiniteFive
- repeatFive = replicate 20 5 -- replicate 5 for 20 times
- cycleFive = cycle [5]
- cycleFibn = cycle fibNum'
- takeCycle = take 50 (cycle [1,2,3,4,5,6,7,8,9,10]) -- with parentheses
- takeCycle' = take 50 $ cycle [1,2,3,4,5,6,7,8,9,10] -- same as the above
- dropFibn = drop 5 fibNum' -- drop the first 5 of the list fibNum'
- filterFibn = filter (>5) fibNum' -- print greater than 5 values
- whileFibn = takeWhile (<=89) fibNum' -- print lesser than or equal to 89 values
- mapList = map (*2) [1..10] -- multiply 2 with numbers 1 to 10
- unordList = [545,2,34,87,3,897,56,13] -- some unordered list
- sortList = sort unordList -- sort the unordered list
- firstNum = head fibNum' -- print the first value in the list
- restNum' = tail fibNum' -- print the values in the list but the first value
- lastNum' = last fibNum' -- print the last value in the list
- initNum' = init fibNum' -- print the values in the list but the last value
- prodList = foldr (*) 1 [2,3,4,5] -- same as 2 * (3 * (4 * (5 * 1)))
- subrList = foldl (-) 1 [2,3,4,5] -- same as (((((1) - 5) - 4) - 3) - 2)
- summList = foldl (+) 0 [1..100] -- same as sum [1..100]
- appendList = 1 : []
- appendList' = 1 : 2 : 3 : 4 : 5 : []
- -- Fibonacci Numbers generation
- fibonacci = 0 : 1 : zipWith (+) fibonacci (tail fibonacci)
- -- [0,1] ([1]) -> [0,1,1,2] ([1,1,2]) -> ...
- -- Functions
- listFunction = [x * y | x <- [1..5], y <- [1..5]]
- listFunction' = [x * y | x <- [1..5], y <- [1..5], x * y `mod` 3 == 0]
- -- Tuples
- tuple' = ("Raman", 18)
- getName = fst tuple'
- getNumm = snd tuple'
- empName = ["John Doe", "Jane Doe", "Mary Jane", "Ben Dover"]
- empNumm = [1001, 1002, 1003, 1004]
- empList = zip empName empNumm
- -- simple functions
- summ a b = a + b
- prod a b = a * b
- func a b c = summ (prod a b) c
- -- program
- -- to compile the program: ghc program.hs
- -- to run inside ghci: main
- greeting = "Hello, World!"
- --main = do
- -- print greeting
- -- program to take input
- --main = do
- -- putStrLn "Enter name: "
- -- name <- getLine
- -- putStrLn ("Hello, " ++ name ++ "!")
- -- program with function
- -- Haskell is picky about spacing!
- lowerCase :: [Char] -> [Char]
- lowerCase s = [c | c <- s, elem c ['a'..'z']]
- main = do
- let s = lowerCase "Institute of Mathematical Sciences"
- print(s)
- -- list
- : is an infix function that takes single value on its left and a list on its right
- 1 : [2, 3, 4, 5, 6] -- which are of same type (prepending function)
- [1,2,3,4,5,6]
- ++ is also an infix function which appends a list to another list which are of same type
- [1, 2, 3] ++ [4, 5, 6]
- [1,2,3,4,5,6]
- -- quick sorting algorithm function
- f [] = []
- f (x:xs) = f ys ++ [x] ++ f zs
- where
- ys = [a | a <- xs, a <= x]
- zs = [b | b <- xs, b > x]
- -- x = 3 and xs = [1, 4, 2]
- f [3, 1, 4, 2] = f (3:[1, 4, 2]) = f [1, 2] ++ [3] ++ f[4]
- = f [] ++ [1] ++ f[2] ++ [3] ++ [4]
- = [] ++ [1] ++ [2] ++ [3] ++ [4]
- = [1, 2, 3, 4]
- -- type signatures
- Functions map input values to output values, for example, inc maps integers to
- integers. Thus we denote the type of inc as Int -> Int.
- inc :: Int -> Int -- type signature
- inc x = x + 1 -- function equation
- -- multiple arguments
- average :: Float -> Float -> Float
- average a b = (a + b) / 2.0
- average 3.0 4.0 = (3.0 + 4.0) / 2.0 = 3.5
|