-- ---
-- jupyter:
--   jupytext:
--     text_representation:
--       extension: .hs
--       format_name: light
--       format_version: '1.5'
--       jupytext_version: 1.14.4
--   kernelspec:
--     display_name: Haskell
--     language: haskell
--     name: haskell
-- ---

-- # Lists

-- Lists should have elements of same data type

-- +
let numbers = [1,23,5,6,7]

numbers
-- -

-- Like in C, a string is nothing but a list of characters (character array in C).

"hello" == ['h','e','l','l','o']

"hello" ++ " " ++ "world"

['f', 't'] ++ "world"

-- #### Note on performance

[1, 2, 3] ++ [4]

-- The compiler has to walk through the first input before appending.

1 : [2, 3, 4]

-- But prepending is...

'I':"nstantaneous!"

-- ## Lexical comparisons

"abc" < "xyz"

"abcd" < "x"

[21, 0 , 1] > [20, 21, 22]

"hello" /= "world"

-- ## Indexing lists

-- +
numbers

numbers !! 2
-- -

-- indices start at 0.

numbers !! (-1)

-- no negative index :(, instead one should use `last`

-- ## List-ception: list in a list

let b = [[1,2,3,4],[5,3,3,3],[1,2,2,3,4],[1,2,3]]

b ++ [[3, 5, 6]]

b !! 1

b !! 1 !! 1

-- * lists within a list can be of different lengths but they can't be of different types

b ++ [[2.0]]

-- ## List slicing

head b

tail b

last b

init b

-- ![](https://s3.amazonaws.com/lyah/listmonster.png)

head []

length [1, 2, 3]

null []

null [1, 2, 3]

reverse [1, 2, 3]

-- Let's work on the list we defined earlier

numbers

take 2 numbers

take 1 [10, 20, 30]

take 0 numbers

drop 2 numbers

drop 0 numbers

maximum numbers

minimum numbers

sum numbers

-- Oooh that's a nice coincidence :)

product numbers

-- Element of:

elem 23 numbers
23 `elem` numbers  -- usually called this way for readability

-- ## Range

[1..10]

['a'..'z']

['z'..'a']

[10,9..1]

['z','x'..'a']

[0.1,0.3..1]

[0.1,0.2..1]

-- ## Them lazy infinite lists!

take 100 [1..]

-- sum of an arithmetic progression

sumAP start stop step = sum [start,start+step..stop]

sumAP 10 100 1

sumAP 1 10 1

sum [1..10]

-- ### Like itertools

take 10 (cycle [1,2])

take 15 (cycle "YOLO ")

take 10 (repeat 5)

replicate 10 5

replicate 3 "YOLO "

-- # List comprehension

-- Like in math where a set may be defined as:
-- ![](https://s3.amazonaws.com/lyah/setnotation.png)

let s = [2 * x | x <- [1..10]]
s

-- or alternatively,
[2 * x | x <- [1..100], x <= 10] -- Caution don't try [1..] here!

let evenNumbers = [x | x <- [1..100], mod x 2 == 0]
evenNumbers

even 8

odd 8

let oddNumbers = [x | x <- [1..100], odd x]
oddNumbers

-- This involves **filtering**. So in essence the syntax for a list comprehension goes like:
--
-- `[expression | variable <- list, *predicates]`
--
-- Functions taking range as parameter and returning list comprehensions.

boomBangs xs = [ if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x]   

boomBangs [7..13]

-- We can have as many predicates as we want

[x | x <- [10..20], x /= 14, even x]

-- Multiple variable list comprehensions!

[x*y | x <- [1,3..5], y <- [2,4..6]]

-- Behaves like a matrix product flattened out. All possible products.

[ x*y | x <- [2,5,10], y <- [8,10,11], x*y > 50]  -- all possible products more than 50

let nouns = ["hobo","frog","pope"]  
let adjectives = ["lazy","grouchy","scheming"]  
[adjective ++ " " ++ noun | adjective <- adjectives, noun <- nouns] 

filterUpperCase st = [c | c <- st, c `elem` ['A'..'Z']]
filterUpperCase "YodelyOLOLoooO!"

-- # Tuples

-- * can be inhomogenous in data types
-- * type depends on number of components and the type of components
-- * denoted using () just like in Python

[(1,2),(8,11),(4,5)]  -- legal

[(1,2),(8,11,5),(4,5)]  -- illegal

-- ## Function only for pairs

fst (10, 11)  -- first

snd (8, 11) -- second

-- ## Like itertools.izip

zip [1,2,3,4,5] [5,5,5,5,5]

zip [5,3,2,6,2,7,2,5,4,6,6] ["im","a","turtle"] -- stops at max length

zip [1..] ["one","two","three","four","five"]

-- Let's make Haskell sing Drowning pool :)

let num = ["one","two","three","four"]
zip num (repeat "Nothing wrong with me")
zip (init num) (repeat "Something's got to give")

-- # Demo time

-- > Which right triangle that has integers for all sides and all sides equal to or smaller than 10 has a perimeter of 24?
--
-- ![](https://s3.amazonaws.com/lyah/pythag.png)

let triangles = [ (a, b, c) | 
                    c <- [1..10],
                    b <- [1..10],
                    a <- [1..10]]

-- Add Pythogoras theorem and condition that hypotenuse is the longest
let rightTriangles = [(a, b, c) |
                        c <- [1..10],
                        b <- [1..c],
                        a <- [1..c],
                        a^2 + b^2 == c^2]
rightTriangles

-- Add perimeter condition
let rightTriangles' = [(a, b, c) |
                        c <- [1..10],
                        b <- [1..c],
                        a <- [1..c],
                        a^2 + b^2 == c^2, a+b+c==24]
rightTriangles'

StarcoderdataJupyterScriptsDedupFiltered