diff --git a/haskellexample/Haskell Cheat Sheet b/haskellexample/Haskell Cheat Sheet new file mode 100644 index 0000000..6320a7e --- /dev/null +++ b/haskellexample/Haskell Cheat Sheet @@ -0,0 +1,621 @@ +-- Haskell is a functional programming language +-- Everything is immutable so once a value is set it is set forever +-- Functions can be passed as a parameter to other functions +-- Recursion is used often +-- Haskell has no for, while, or technically variables, but it does have +-- constants +-- Haskell is lazy in that it doesn't execute more then is needed and instead +-- just checks for errors +  +-- Best Free Haskell Book +-- http://learnyouahaskell.com/chapters +  +-- Type ghci to open it up in your terminal +-- Load script with :l haskelltut +-- :quit exits the GHCi +  +-- Import a module +import Data.List +import System.IO +  +{- +Beginning of multiline comment +-} +  +-- ---------- DATA TYPES ---------- +-- Haskell uses type inference meaning it decides on the data type based on the -- value stored in it +-- Haskell is statically typed and can't switch type after compiling +-- Values can't be changed (Immutable) +-- You can use :t in the terminal to get the data type (:t value) +  +-- Int : Whole number -2^63 - 2^63 +-- :: Int defines that maxInt is an Int +maxInt = maxBound :: Int +minInt = minBound :: Int +  +-- Integer : Unbounded whole number +  +-- Float : Single precision floating point number +-- Double : Double precision floating point number (11 pts precision) +bigFloat = 3.99999999999 + 0.00000000005 +  +-- Bool : True or False +-- Char : Single unicode character denoted with single quotes +-- Tuple : Can store a list made up of many data types +  +-- You declare the permanent value of a variable like this +always5 :: Int +always5 = 5 +  +-- ---------- MATH ---------- +-- Something crazy to start +sumOfVals = sum [1..1000] +  +addEx = 5 + 4 +subEx = 5 - 4 +multEx = 5 * 4 +divEx = 5 / 4 +  +-- mod is a prefix operator +modEx = mod 5 4 +  +-- With back ticks we can use it as an infix operator +modEx2 = 5 `mod` 4 +  +-- Negative numbers must be surrounded with parentheses +negNumEx = 5 + (-4) +  +-- If you define an Int you must use fromIntegral to use it with sqrt +-- :t sqrt shows that it returns a floating point number +num9 = 9 ::Int +sqrtOf9 = sqrt (fromIntegral num9) +  +-- Built in math functions +piVal = pi +ePow9 = exp 9 +logOf9 = log 9 +squared9 = 9 ** 2 +truncateVal = truncate 9.999 +roundVal = round 9.999 +ceilingVal = ceiling 9.999 +floorVal = floor 9.999 +  +-- Also sin, cos, tan, asin, atan, acos, sinh, tanh, cosh, asinh, atanh, acosh +  +trueAndFalse = True && False +trueOrFalse = True || False +notTrue = not(True) +  +-- Remember you use :t in the terminal to get the data type (:t value) +-- You can also see how functions use data types with :t +  +-- :t (+) = Num a => a -> a -> a +-- Type a is in the type class num, we receive 2 of them and return 1 +  +-- :t truncate = (RealFrac a, Integral b) => a -> b +  +-- ---------- LISTS ---------- +-- Lists are singly linked and you can only add to the front of it + +-- Lists store many elements of the same type +primeNumbers = [3,5,7,11] +  +-- Concatenate lists (Can be slow if your using a large list) +morePrimes = primeNumbers ++ [13,17,19,23,29] +  +-- You can use the cons operator to construct a list +favNums = 2 : 7 : 21 : 66 : [] +  +-- You can make a list of lists +multList = [[3,5,7],[11,13,17]] +  +-- Quick way to add 1 value to the front of a list +morePrimes2 = 2 : morePrimes +  +-- Get number of elements in the list +lenPrime = length morePrimes2 +  +-- Reverse the list +revPrime = reverse morePrimes2 +  +-- return True if list is empty +isListEmpty = null morePrimes2 +  +-- Get the number in index 1 +secondPrime = morePrimes2 !! 1 +  +-- Gets the 1st value in a list +firstPrime = head morePrimes2 +  +-- Gets the last value +lastPrime = last morePrimes2 +  +-- Gets everything but the first value +primeTail = tail morePrimes2 +  +-- Gets everything but the last value +primeInit = init morePrimes2 +  +-- Get specified number of elements from the front of a list +first3Primes = take 3 morePrimes2 +  +-- Return values left after removing specified values +removedPrimes = drop 3 morePrimes2 +  +-- Check if value is in list +is7InList = 7 `elem` morePrimes2 +  +-- Get max value +maxPrime = maximum morePrimes2 +  +-- Get minimum value +minPrime = minimum morePrimes2 +  +-- Sum values in list +sumPrimes = sum morePrimes2 +  +-- Get product of values in list (Value all can evenly divide by) +newList = [2,3,5] +prodPrimes = product newList +  +-- Create list from 0 to 10 +zeroToTen = [0..10] +  +-- Create list of evens by defining the step between the first 2 values +evenList = [2,4..20] +  +-- You can use letters as well +letterList = ['A','C'..'Z'] +  +-- You can generate an infinite list and Haskell will only generate what you +-- need +infinPow10 = [10,20..] +  +-- repeat repeats a value a defined number of times +many2s = take 10 (repeat 2) +  +-- replicate generates a value a specified number of times +many3s = replicate 10 3 +  +-- cycle replicates the values in a list indefinitely +cycleList = take 10 (cycle [1,2,3,4,5]) +  +-- You could perform operations on all values in a list +-- Cycle through the list storing each value in x which is multiplied by 2 and +-- then stored in a new list +listTimes2 = [x * 2 | x <- [1..10]] +  +-- We can filter the results with conditions +listTimes3 = [x * 3 | x <- [1..20], x*3 <= 50] +  +-- Return all values that are divisible by 13 and 9 +divisBy9N13 = [x | x <- [1..500], x `mod` 13 == 0, x `mod` 9 == 0] +  +-- Sort a list +sortedList = sort [9,1,8,3,4,7,6] +  +-- zipwith can combine lists using a function +sumOfLists = zipWith (+) [1,2,3,4,5] [6,7,8,9,10] +  +-- Filter returns a list of items that match a condition +listBiggerThen5 = filter (>5) sumOfLists +  +-- takeWhile returns list items until the condition is false +evensUpTo20 = takeWhile (<=20) [2,4..] +  +-- foldl applies the operation on each item of a list +-- foldr applies these operations from the right +multOfList = foldl (*) 1 [2,3,4,5] +  +-- ---------- LIST COMPREHENSION ---------- +  +-- We can generate a list from 1 to 10 to the power of 3 +pow3List = [3^n | n <- [1..10]] +  +-- We can filter the results to only show values divisible by 9 +pow3ListDiv9 = [3^n | n <- [1..10], 3^n `mod` 9 == 0] +  +-- Generate a multiplication table by multiplying x * y where y has the values +-- 1 through 10 and where x does as well +multTable = [[x * y | y <- [1..10]] | x <- [1..10]] +  +-- ---------- TUPLES ---------- +-- Stores list of multiple data types, but has a fixed size +  +randTuple = (1,"Random tuple") +  +-- A tuple pair stores 2 values +bobSmith = ("Bob Smith",52) +  +-- Get the first value +bobsName = fst bobSmith +  +-- Get the second value +bobsAge = snd bobSmith +  +-- zip can combine values into tuple pairs +names = ["Bob","Mary","Tom"] +addresses = ["123 Main","234 North","567 South"] +  +namesNAddress = zip names addresses +  +-- ---------- FUNCTIONS ---------- +-- ghc --make haskelltut compiles your program and executes the main function +  +-- Functions must start with lowercase letters +  +-- We can define functions and values in the GHCi with let +-- let num7 = 7 +-- let getTriple x = x * 3 +  +-- getTriple num7 = 21 +  +-- main is a function that can be called in the terminal with main +main = do + -- Prints the string with a new line + putStrLn "What's your name: " + + -- Gets user input and stores it in name + -- <- Pulls the name entered from an IO action + name <- getLine + + putStrLn ("Hello " ++ name) + +-- Create function addMe +-- x is a parameter and the operation follows the equals sign +-- The data type passed in will work if it makes sense +-- Every function must return something +-- A function name can't begin with a capital letter +-- A function that doesn't receive parameters is called a definition or name +  +-- You can define a type declaration for functions +-- funcName :: param1 -> param2 -> returnType +addMe :: Int -> Int -> Int +  +-- funcName param1 param2 = operations (Returned Value) +-- Execute with : addMe 4 5 +addMe x y = x + y +  +-- Without type declaration you can add floats as well +sumMe x y = x + y +  +-- You can also add tuples : addTuples (1,2) (3,4) = (4,6) +addTuples :: (Int, Int) -> (Int, Int) -> (Int, Int) +addTuples (x, y) (x2, y2) = (x + x2, y + y2) +  +-- You can perform different actions based on values +whatAge :: Int -> String +whatAge 16 = "You can drive" +whatAge 18 = "You can vote" +whatAge 21 = "You're an adult" +  +-- The default +whatAge x = "Nothing Important" +  +-- Define that we expect an Int in and out +factorial :: Int -> Int +  +-- If 0 return a 1 (Recursive Function) +factorial 0 = 1 +factorial n = n * factorial (n - 1) +  +-- 3 * factorial (2) : 6 +-- 2 * factorial (1) : 2 +-- 1 * factorial (0) : 1 +  +-- You could also use product to calculate factorial +productFactorial n = product [1..n] +  +-- We can use guards that provide different actions based on conditions +isOdd :: Int -> Bool +isOdd n + -- if the modulus using 2 equals 0 return False + | n `mod` 2 == 0 = False + + -- Else return True + | otherwise = True + +-- This could be shortened to +isEven n = n `mod` 2 == 0 +  +-- Use guards to define the school to output +whatGrade :: Int -> String +whatGrade age + | (age >= 5) && (age <= 6) = "Kindergarten" + | (age > 6) && (age <= 10) = "Elementary School" + | (age > 10) && (age <= 14) = "Middle School" + | (age > 14) && (age <= 18) = "High School" + | otherwise = "Go to college" + +-- The where clause keeps us from having to repeat a calculation +batAvgRating :: Double -> Double -> String +batAvgRating hits atBats + | avg <= 0.200 = "Terrible Batting Average" + | avg <= 0.250 = "Average Player" + | avg <= 0.280 = "Your doing pretty good" + | otherwise = "You're a Superstar" + where avg = hits / atBats + +-- You can access list items by separating letters with : or get everything but +-- the first item with xs +getListItems :: [Int] -> String +getListItems [] = "Your list is empty" +getListItems (x:[]) = "Your list contains " ++ show x +getListItems (x:y:[]) = "Your list contains " ++ show x ++ " and " ++ show y +getListItems (x:xs) = "The first item is " ++ show x ++ " and the rest are " + ++ show xs + +-- We can also get values with an As pattern +getFirstItem :: String -> String +getFirstItem [] = "Empty String" +getFirstItem all@(x:xs) = "The first letter in " ++ all ++ " is " + ++ [x] + +-- ---------- HIGHER ORDER FUNCTIONS ---------- +-- Passing of functions as if they are variables +  +times4 :: Int -> Int +times4 x = x * 4 +  +-- map applies a function to every item in the list +listTimes4 = map times4 [1,2,3,4,5] +  +-- Let's make map +multBy4 :: [Int] -> [Int] +multBy4 [] = [] +  +-- Takes the 1st value off the list x, multiplies it by 4 and stores it in the +-- new list +-- xs is then passed back into multBy4 until there is nothing left of the list -- to process (Recursion) +multBy4 (x:xs) = times4 x : multBy4 xs +  +-- Check if strings are equal with recursion +areStringsEq :: [Char] -> [Char] -> Bool +areStringsEq [] [] = True +areStringsEq (x:xs) (y:ys) = x == y && areStringsEq xs ys +areStringsEq _ _ = False +  +-- PASSING A FUNCTION INTO A FUNCTION +-- (Int -> Int) says we expect a function that receives an Int and returns an +-- Int +doMult :: (Int -> Int) -> Int +  +-- We receive the function and pass 3 into it +doMult func = func 3 +  +-- We pass in the function that multiplies by 4 +num3Times4 = doMult times4 +  +-- RETURNING A FUNCTION FROM A FUNCTION +getAddFunc :: Int -> (Int -> Int) +  +-- We can pass in the values to the function +getAddFunc x y = x + y +  +-- We could also get a function that adds 3 for example +adds3 = getAddFunc 3 +  +fourPlus3 = adds3 4 +  +-- We could use this function with map as well +threePlusList = map adds3 [1,2,3,4,5] +  +-- ---------- LAMBDA ---------- +-- How we create functions without a name +-- \ represents lambda then you have the arguments -> and result +  +dbl1To10 = map (\x -> x * 2) [1..10] +  +-- ---------- CONDITIONALS ---------- +  +-- Comparison Operators : < > <= >= == /= +-- Logical Operators : && || not +  +-- Every if statement must contain an else +doubleEvenNumber y = + if (y `mod` 2 /= 0) + then y + else y * 2 + +-- We can use case statements +getClass :: Int -> String +getClass n = case n of + 5 -> "Go to Kindergarten" + 6 -> "Go to elementary school" + _ -> "Go some place else" + +-- ---------- MODULES ---------- +-- You can group functions into modules. I showed previously how to load them +-- You can create your own module by creating a file that contains all your +-- functions and then list the functions at the top like this +-- module SampFunctions (getClass, doubleEvenNumber) where +-- They can then be imported with import SampFunctions +  +-- ---------- ENUMERATION TYPES ---------- +-- Used when you want a list of possible types +-- Provide name, a list and then Show converts into a String for printing +  +data BaseballPlayer = Pitcher + | Catcher + | Infield + | Outfield + deriving Show +  +barryBonds :: BaseballPlayer -> Bool +barryBonds Outfield = True +  +barryInOF = print(barryBonds Outfield) +  +-- ---------- CUSTOM TYPES ---------- +-- You can store multiple values sort of like a struct to create custom types +data Customer = Customer String String Double + deriving Show + +-- Define Customer and its values +tomSmith :: Customer +tomSmith = Customer "Tom Smith" "123 Main St" 20.50 +  +-- Define how we'll find the right customer (By Customer) and the return value +getBalance :: Customer -> Double +getBalance (Customer _ _ b) = b +  +tomSmithBal = print (getBalance tomSmith) +  +-- We can define a type with all possible values +data RPS = Rock | Paper | Scissors +  +shoot :: RPS -> RPS -> String +shoot Paper Rock = "Paper Beats Rock" +shoot Rock Scissors = "Rock Beats Scissors" +shoot Scissors Paper = "Scissors Beat Paper" +shoot Scissors Rock = "Scissors Loses to Rock" +shoot Paper Scissors = "Paper Loses to Scissors" +shoot Rock Paper = "Rock Loses to Paper" +shoot _ _ = "Error" +  +-- We could define 2 versions of a type +-- First 2 floats are center coordinates and then radius for Circle +-- First 2 floats are for upper left hand corner and bottom right hand corner +-- for the Rectangle +data Shape = Circle Float Float Float | Rectangle Float Float Float Float + deriving (Show) +  +-- :t Circle = Float -> Float -> Float -> Shape +  +-- Create a function to calculate area of shapes +area :: Shape -> Float +area (Circle _ _ r) = pi * r ^ 2 +area (Rectangle x y x2 y2) = (abs (x2 - x)) * (abs (y2 -y)) +  +-- Could also be area (Rectangle x y x2 y2) = (abs $ x2 - x) * (abs $ y2 -y) +-- $ means that anything that comes after it will take precedence over anything +-- that comes before (Alternative to adding parentheses) +  +-- The . operator allows you to chain functions to pass output on the right to +-- the input on the left +-- sumValue = putStrLn (show (1 + 2)) becomes +sumValue = putStrLn . show $ 1 + 2 +  +-- Get area of shapes +areaOfCircle = area (Circle 50 60 20) +areaOfRectangle = area $ Rectangle 10 10 100 100 +  +-- ---------- TYPE CLASSES ---------- +-- Num, Eq, Ord and Show are type classes +-- Type classes correspond to sets of types which have certain operations +-- defined for them. +-- Polymorphic functions, which work with multiple parameter types, define +-- the types it works with through the use of type classes +-- For example (+) works with parameters of the type Num +-- :t (+) = Num a => a -> a -> a +-- This says that for any type a, as long as a is an instance of Num, + can take +-- 2 values and return an a of type Num +  +-- Create an Employee and add the ability to check if they are equal +data Employee = Employee { name :: String, +    position :: String, +    idNum :: Int +    } deriving (Eq, Show) +    +samSmith = Employee {name = "Sam Smith", position = "Manager", idNum = 1000} +pamMarx = Employee {name = "Pam Marx", position = "Sales", idNum = 1001} +  +isSamPam = samSmith == pamMarx +  +-- We can print out data because of show +samSmithData = show samSmith +  +-- Make a type instance of the typeclass Eq and Show +data ShirtSize = S | M | L +  +instance Eq ShirtSize where + S == S = True + M == M = True + L == L = True + _ == _ = False +  +instance Show ShirtSize where + show S = "Small" + show M = "Medium" + show L = "Large" + +-- Check if S is in the list +smallAvail = S `elem` [S, M, L] +  +-- Get string value for ShirtSize +theSize = show S +  +-- Define a custom typeclass that checks for equality +-- a represents any type that implements the function areEqual +class MyEq a where + areEqual :: a -> a -> Bool + +-- Allow Bools to check for equality using areEqual +instance MyEq ShirtSize where + areEqual S S = True + areEqual M M = True + areEqual L L = True + areEqual _ _ = False +  +newSize = areEqual M M +  +-- ---------- I/O ---------- +  +sayHello = do + -- Prints the string with a new line + putStrLn "What's your name: " + + -- Gets user input and stores it in name + name <- getLine + + -- $ is used instead of the parentheses + putStrLn $ "Hello " ++ name + +-- File IO +-- Write to a file +writeToFile = do +  + -- Open the file using WriteMode + theFile <- openFile "test.txt" WriteMode + + -- Put the text in the file + hPutStrLn theFile ("Random line of text") + + -- Close the file + hClose theFile + +readFromFile = do +  + -- Open the file using ReadMode + theFile2 <- openFile "test.txt" ReadMode + + -- Get the contents of the file + contents <- hGetContents theFile2 + putStr contents + + -- Close the file + hClose theFile2 + +-- ---------- EXAMPLE : FIBONACCI SEQUENCE ---------- +  +-- Calculate the Fibonacci Sequence +-- 1, 1, 2, 3, 5, 8, ... +  +-- 1 : 1 : says to add 2 1s to the beginning of a list +-- | for every (a, b) add them +-- <- stores a 2 value tuple in a and b +-- tail : get all list items minus the first +-- zip creates pairs using the contents from 2 lists being the lists fib and the +-- list (tail fib) +  +fib = 1 : 1 : [a + b | (a, b) <- zip fib (tail fib) ] +  +-- First time through fib = 1 and (tail fib) = 1 +-- The list is now [1, 1, 2] because a: 1 + b: 1 = 2 +  +-- The second time through fib = 1 and (tail fib) = 2 +-- The list is now [1, 1, 2, 3] because a: 1 + b: 2 = 3 +  +fib300 = fib !! 300 -- Gets the value stored in index 300 of the list +  +-- take 20 fib returns the first 20 Fibonacci numbers