work-site/content/courses/h4life/h4life-funcs.hs

215 lines
5.3 KiB
Haskell
Raw Normal View History

2018-09-22 23:40:20 +02:00
{- funcs.hs
This file contains some of the examples to be shown in the first class
of the course "Haskell for Life", by Sergiu Ivanov (sivanov@lacl.fr):
http://lacl.fr/~sivanov/doku.php?id=en:haskell_for_life
This file is distributed under the Creative Commons Attribution Alone
licence.-}
{- The examples shown in the first part. -}
add x y = x + y
factorial :: Int -> Int
factorial x = if x == 0
then 1
else x * factorial (x-1)
fibonacci :: Int -> Int
fibonacci n = if n == 1
then 1
else if n == 2
then 1
else fibonacci (n-1)
+ fibonacci (n-2)
myNot :: Bool -> Bool
myNot x = if x == True then False else True
myNot1 :: Bool -> Bool
myNot1 True = False
myNot1 False = True
factorial1 :: Int -> Int
factorial1 0 = 1
factorial1 n = n * factorial1 (n-1)
fibonacci1 :: Int -> Int
fibonacci1 1 = 1
fibonacci1 2 = 1
fibonacci1 n = fibonacci1 (n-1) + fibonacci1 (n-2)
fibonacci2 :: Int -> Int
fibonacci2 n | n <= 2 = 1
fibonacci2 n | n > 2 = fibonacci2 (n-1) + fibonacci2 (n-2)
myHead :: [a] -> a
myHead (h:_) = h
myTail :: [a] -> [a]
myTail (_:xs) = xs
{- The fun starts here.
This section contains implementations of the functions from Data.List
and Prelude. Our implementation of the function foo is called
myFoo.-}
-- | Check whether the list is empty.
myNull :: [a] -> Bool
myNull [] = True
myNull _ = False
-- | Compute the length of the list.
myLength :: [a] -> Int
myLength [] = 0
myLength (x:xs) = 1 + length xs
-- | Get the last element of the list.
--
-- list = myInit list ++ [myLast list]
myLast :: [a] -> a
myLast [x] = x
myLast (x:xs) = myLast xs
-- | Get all elements of the list, but the last one.
--
-- list = myInit list ++ [myLast list]
myInit :: [a] -> [a]
myInit [x] = []
myInit (x:xs) = x : myInit xs
-- | append = (++)
append :: [a] -> [a] -> [a]
append [] ys = ys
append (x:xs) ys = x:append xs ys
-- | Reverses the list.
--
-- In typical functional implementations, '(++)' needs to traverse the
-- first list entirely (cf. 'append'). So this implementation of
-- "reverse" would need to traverse the list at every recursive call.
-- The overall complexity would thus be O(n^2/2).
--
-- In Haskell, '(++)' is implemented with optimisation and may take
-- constant time to run.
badReverse :: [a] -> [a]
badReverse [] = []
badReverse (x:xs) = badReverse xs ++ [x]
-- | Reverses the list.
--
-- This implementation only traverses the list once.
myReverse :: [a] -> [a]
myReverse xs = reverse' xs []
where reverse' [] acc = acc
reverse' (x:xs) acc = reverse' xs (x:acc)
myTake :: Int -> [a] -> [a]
myTake _ [] = []
myTake 0 _ = []
myTake n (x:xs) = x:myTake (n-1) xs
myDrop :: Int -> [a] -> [a]
myDrop _ [] = []
myDrop 0 xs = xs
myDrop n (x:xs) = myDrop (n-1) xs
-- | Glues two lists together.
--
-- myZip [1,2] [3,4] == [(1,2),(3,4)]
myZip :: [a] -> [b] -> [(a,b)]
myZip [] _ = []
myZip _ [] = []
myZip (x:xs) (y:ys) = (x,y):myZip xs ys
-- | Checks whether an element is part of the list.
--
-- 'Eq a =>' requires that objects of type 'a' can be "compared".
--
-- We add two pattern guards to handle the cases when 'y == x' and
-- 'y /= x'. 'otherwise' is a condition which is always true.
myElem :: Eq a => a -> [a] -> Bool
myElem _ [] = False
myElem y (x:xs) | y == x = True
| otherwise = myElem y xs
-- | Given a function and a list, returns a list containing the
-- elements for which the function is true.
--
-- myFilter odd [1..5] == [1,3,5].
--
-- 'odd' is the function returning 'True' for odd numbers.
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter _ [] = []
myFilter p (x:xs) | p x = x:myFilter p xs
| otherwise = myFilter p xs
-- | Applies a function to all elements of a list and returns the
-- results.
myMap :: (a -> b) -> [a] -> [b]
myMap _ [] = []
myMap f (x:xs) = f x:myMap f xs
myFoldr :: (a -> b -> b) -> b -> [a] -> b
myFoldr _ r0 [] = r0
myFoldr f r0 (x:xs) = f x (myFoldr f r0 xs)
{- This section contains the reimplementations of some of the
functions from Data.List and the standard Prelude using folds. Our
implementation of the function foo is called fldFoo.-}
-- | Sums up the elements of the list.
fldSum :: [Int] -> Int
fldSum xs = foldl (+) 0 xs
-- | Checks whether the given function returns 'True' for all elements
-- of the given list.
fldAll :: (a -> Bool) -> [a] -> Bool
fldAll f xs = foldl (\r x -> (f x) && r) True xs
-- | Checks whether the given function returns 'True' for at least one
-- element of the list.
fldAny :: (a -> Bool) -> [a] -> Bool
fldAny f xs = foldl (\r x -> (f x) || r) False xs
-- | Concatenates all the lists in the given list.
--
-- [[1,2],[3,4]] = [1,2,3,4]
fldConcat :: [[a]] -> [a]
fldConcat xs = foldl (++) [] xs
fldFilter :: (a -> Bool) -> [a] -> [a]
fldFilter f xs = reverse (foldl test [] xs)
where test r x | f x = x:r
| otherwise = r
fldMap' :: (a -> b) -> [a] -> [b]
fldMap' f xs = reverse (foldl (\r x -> f x:r) [] xs)
-- The clever Pentalog guy showed me this solution.
fldMap :: (a -> b) -> [a] -> [b]
fldMap f = foldr ((:) . f) []
-- Bubble sort.
bubblesort :: Ord a => [a] -> [a]
bubblesort xs = iterate bubble xs !! (length xs - 1)
where bubble [] = []
bubble [x] = [x]
bubble (x:y:xs) | x < y = x : bubble (y:xs)
| otherwise = y : bubble (x:xs)