Skip to content

Instantly share code, notes, and snippets.

@willbasky
Created March 27, 2019 19:55
Show Gist options
  • Save willbasky/44dc74289b39a2d6820df85fc784901e to your computer and use it in GitHub Desktop.
Save willbasky/44dc74289b39a2d6820df85fc784901e to your computer and use it in GitHub Desktop.
fibs :: [Integer]
fibs = 1 : scanl (+) 1 fibs
fibsN :: Int -> Integer
fibsN x = fibs !! x
fibsT :: Int -> Integer
fibsT x = last $ take x fibs
-- Scans Exercises
-- 1. Modify your fibs function to only return the first 20 Fibonacci numbers.
fibs20 :: [Integer]
fibs20 = take 20 go
where
go = 1 : scanl (+) 1 go
-- 2. Modify fibs to return the Fibonacci numbers that are less than 100.
fibsLess100 :: [Integer]
fibsLess100 = takeWhile (<= 100) go
where
go = 1 : scanl (+) 1 go
-- 3. Try to write the factorial function from Recursion as a scan.
-- You’ll want scanl again, and your start value will be 1. Warning:
-- this will also generate an infinite list, so you may want to pass it
-- through a take function or similar.
fac :: [Integer]
fac = scanl (*) 1 [1..]
facN :: Int -> Integer
facN x = fac !! x
-- Warm-up and review
-- 1. stop-vowel-stop
stops :: String
stops = "pbtdkg"
vowels :: String
vowels = "aeiou"
triples :: [(Char,Char,Char)]
triples = [(x,y,z) | x <- stops, y <- vowels, z <- stops]
-- 1.b
triplesP :: [(Char,Char,Char)]
triplesP = [(x,y,z) | x <- stops, y <- vowels, z <- stops, x == 'p']
-- 1.c
nouns :: [String]
nouns = ["fun", "cow", "boy", "cake", "umbrella"]
verbs :: [String]
verbs = ["makes", "eats", "gets", "proves"]
nvn :: [(String,String,String)]
nvn = [(x,y,z) | x <- nouns, y <- verbs, z <- nouns]
-- 2.
seekritFunc :: String -> Int
seekritFunc x = div (sum (map length (words x))) (length (words x))
-- 3.
seekritFunc2 :: String -> Int
seekritFunc2 x = div w n
where
(w,n) = foldr (\y (s,l) -> (length y + s, 1 + l)) (0,0) $ words x
-- Rewriting functions using folds
-- 1. myOr returns True if any Bool in the list is True.
myOr :: [Bool] -> Bool
myOr = foldr (||) False
-- 2. myAny returns True if a -> Bool applied to any of the values in the
-- list returns True.
myAny :: (a -> Bool) -> [a] -> Bool
myAny predicate = foldr (\x acc -> bool acc True (predicate x)) False
-- 3. Write two versions of myElem. One version should use folding
-- and the other should use any.
myElem :: Eq a => a -> [a] -> Bool
myElem e = foldr (\x acc -> bool acc True (x == e)) False
myElemAny :: Eq a => a -> [a] -> Bool
myElemAny e = any (== e)
-- 4. Implement myReverse, don’t worry about trying to make it lazy.
myReverse :: [a] -> [a]
myReverse = foldl (flip (:)) []
-- 5. Write myMap in terms of foldr. It should have the same behavior
-- as the built-in map.
myMap :: (a -> b) -> [a] -> [b]
myMap f = foldr (\x acc -> f x : acc) []
-- 6. Write myFilter in terms of foldr. It should have the same behav-
-- ior as the built-in filter.
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter predicate = foldr (\x acc -> bool acc (x:acc) (predicate x)) []
-- 7. squish flattens a list of lists into a list
squish :: [[a]] -> [a]
squish = foldr (++) []
-- 8. squishMap maps a function over a list and concatenates the results.
squishMap :: (a -> [b]) -> [a] -> [b]
squishMap f = foldr (\x acc -> f x ++ acc) []
-- 9. squishAgain flattens a list of lists into a list. This time re-use the
-- squishMap function.
squishAgain :: [[a]] -> [a]
squishAgain = squishMap id
-- 10. myMaximumBy takes a comparison function and a list and returns
-- the greatest element of the list based on the last value that the
-- comparison returned GT for.
myMaximumBy :: (a -> a -> Ordering) -> [a] -> a
myMaximumBy _ [] = error "Empty List"
myMaximumBy comparing (x:xs) = foldr (\y acc -> if comparing y acc == GT then y else acc) x (x:xs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment