Skip to content

Instantly share code, notes, and snippets.

@hherhold
Created February 27, 2013 11:49
Show Gist options
  • Save hherhold/5047359 to your computer and use it in GitHub Desktop.
Save hherhold/5047359 to your computer and use it in GitHub Desktop.
Basic list functions implemented "by hand" for practice while reading "Real World Haskell".
-- Implementing basic list functions for fun and profit
import Data.List
myLength :: [a] -> Int
myLength = foldl (\acc _ -> acc + 1) 0
myLength' :: [a] -> Int
myLength' [] = 0
myLength' (x:xs) = 1 + myLength' xs
myLength'' :: [a] -> Int
myLength'' = foldr (\_ acc -> acc + 1) 0
myNull :: [a] -> Bool
myNull [] = True
myNull _ = False
myHead :: [a] -> a
myHead [] = error "empty list"
myHead (x:_) = x
myTail :: [a] -> [a]
myTail [] = error "empty list"
myTail (_:xs) = xs
myLast :: [a] -> a
myLast [] = error "empty list"
myLast [x] = x
myLast (x:xs) = myLast xs
myInit :: [a] -> [a]
myInit [] = error "empty list"
myInit [x] = []
myInit (x:y:[]) = [x]
myInit (x:xs) = x : myInit xs
myAnd :: [Bool] -> Bool
myAnd = foldl (&&) True
myAnd' :: [Bool] -> Bool
myAnd' [] = True
myAnd' (x:xs) = x && myAnd xs
myOr :: [Bool] -> Bool
myOr = foldl (||) False
myOr' :: [Bool] -> Bool
myOr' [] = False
myOr' (x:xs) = x || myOr xs
myAll :: (a -> Bool) -> [a] -> Bool
myAll p xs = foldl (\acc x -> acc && (p x)) True xs
myAll' :: (a -> Bool) -> [a] -> Bool
myAll' _ [] = True
myAll' p [x] = p x
myAll' p (x:xs) = p x && myAll' p xs
myAny :: (a -> Bool) -> [a] -> Bool
myAny p xs = foldl (\acc x -> acc || (p x)) False xs
myAny' :: (a -> Bool) -> [a] -> Bool
myAny' _ [] = False
myAny' p [x] = p x
myAny' p (x:xs) = p x || myAny' p xs
myTake :: Int -> [a] -> [a]
myTake 0 xs = []
myTake _ [] = []
myTake n (x:xs) = (x:(myTake (n - 1) xs))
myDrop :: Int -> [a] -> [a]
myDrop 0 xs = xs
myDrop _ [] = []
myDrop n (x:xs) = myDrop (n - 1) xs
mySplitAt :: Int -> [a] -> ([a],[a])
mySplitAt n xs = (myTake n xs, myDrop n xs)
myTakeWhile :: (a -> Bool) -> [a] -> [a]
myTakeWhile p [] = []
myTakeWhile p (x:xs) | p x = (x:(myTakeWhile p xs))
| otherwise = []
myDropWhile :: (a -> Bool) -> [a] -> [a]
myDropWhile p [] = []
myDropWhile p (x:xs) | p x = myDropWhile p xs
| otherwise = (x:xs)
mySpan :: (a -> Bool) -> [a] -> ([a],[a])
mySpan p xs = (takeWhile p xs, dropWhile p xs)
myBreak :: (a -> Bool) -> [a] -> ([a],[a])
myBreak p xs = (takeWhile (not . p) xs, dropWhile (not . p) xs)
myElem :: (Eq a) => a -> [a] -> Bool
myElem _ [] = False
myElem n [x] = n == x
myElem n (x:xs) = if n == x then True
else myElem n xs
myNotElem :: (Eq a) => a -> [a] -> Bool
myNotElem n xs = not $ (myElem n xs)
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter _ [] = []
myFilter p (x:xs) | (p x) = (x:(myFilter p xs))
| otherwise = myFilter p xs
myIsPrefixOf :: (Eq a) => [a] -> [a] -> Bool
myIsPrefixOf a b = a == (take (length a) b)
myIsInfixOf :: (Eq a) => [a] -> [a] -> Bool
myIsInfixOf needle haystack = any (myIsPrefixOf needle) (tails haystack)
myIsSuffixOf :: (Eq a) => [a] -> [a] -> Bool
myIsSuffixOf a b = (reverse a) `myIsPrefixOf` (reverse b)
myZip :: [a] -> [b] -> [(a,b)]
myZip _ [] = []
myZip [] _ = []
myZip (x:xs) (y:ys) = ((x,y):myZip xs ys)
myZipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
myZipWith _ _ [] = []
myZipWith _ [] _ = []
myZipWith f (x:xs) (y:ys) = (f x y):myZipWith f xs ys
-- Adapted from source for base for better understanding.
myLines :: String -> [String]
myLines [] = []
myLines s = l : case s' of
[] -> []
-- This peels off the \n left over by break.
(_:s'') -> myLines s''
where (l, s') = break (== '\n') s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment