214 lines
5.3 KiB
Haskell
214 lines
5.3 KiB
Haskell
{- 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)
|