Henry Laxen July 3, 2009

This file can be loaded into ghci and executed. You are encouraged to do so.

> import Prelude hiding ((.), (^), (>), (/), elem, foldl, foldl1)
> import MPS
> import Control.Category hiding ((.))
> hamlet = ["2", "b" , "or", "not", "to", "be"]
. is used to pass an argument to the function on the right, also called apply and send_to later
> (.) :: a -> (a -> b) -> b  

Notice that . binds less tightly than function arguments, so [1..5].drop 2 is the same as drop 2 [1..5]

> t1 = [1..5].head          -- 1
> t1a = apply [1..5] head   -- 1
> t1b = send_to [1..5] head -- 1
> t2 = [1..5].drop 2        --  [3,4,5]

> is left to right function composition, read it as then

> (>) :: (Category cat) => cat a b -> cat b c -> cat a c
> t3 = tail > length $ [1..5] -- tail then length, is 4

^ is an infix fmap

> (^) :: (Functor f) => f a -> (a -> b) -> f b
> t4 = [1..5] ^ (1+) -- is [2,3,4,5,6]

/ is a FilePath joiner, not division, see System.FilePath.Posix.combine

> (/) :: FilePath -> FilePath -> FilePath
> t5 = "usr" / "local" / "bin" -- is "usr/local/bin" on Linux

join is intercalate, it inserts the first list, (usually a String) in between each of the seconds lists, (usually a list of Strings)

> join :: [a] -> [[a]] -> [a]
> t6 = ["2 b", "to be"].join " or not " -- is "2 b or not to be"

first .. tenth select the corresponding element of a list

> first :: [a] -> a
> t7 = [1..5].third -- is 3

unique is a synonym for nub, but requires ord. It returns the unique elements of list

> unique :: (Ord a) => [a] -> [a]
> t8 = unique ([1..5] ++ [3..8]) -- is [1,2,3,4,5,6,7,8]

is_unique returns True if there are no duplicate elements in a list

> is_unique :: (Ord a) => [a] -> Bool
> t9 = (is_unique [1,2,3,4], is_unique [1,1,2,3]) -- is (True,False)

same returns True if all the elements of a list are the same

> same :: (Ord a) => [a] -> Bool
> t10 = same "aaa" -- is True

times is like an infix replicate, to be used with the new .

> times :: a -> Int -> [a]
> t11 = 3.times 'a' -- is "aaa"

upto and downto are infix ranges, to be used with the new .

> upto :: (Enum a) => a -> a -> [a]
> t12 = 1.upto 3 -- is [1,2,3]
> t13 = 3.downto 1 -- is [3,2,1]

remove_at, insert_at and replace_at are all similar, and do their thing at a particular position of a given list.

> remove_at :: Int -> [a] -> [a]  
> insert_at, replace_at :: Int -> a -> [a] -> [a]  
> t14 = insert_at  2 'a' "blb" -- is "blab"

at is list indexing

> at :: Int -> [a] -> a  
> t15 = at 2 "abcd" -- is 'c'

slice takes a slice out of a list, if the list is [0..n] then slice a b is

> [x] such that a  <=  x  <  b   
> slice :: Int -> Int -> [a] -> [a]  
> t16 = slice 2 4 [1..5] -- is [3,4] (remember 0 indexing!)

cherry_pick picks a set of elements out of a list based on a list if indices

> cherry_pick :: [Int] -> [a] -> [a]
> t17 = cherry_pick [5,0,1] hamlet -- ["be","2","b"]

reduce and **reduce\'** are synonyms for foldl1, but all the arguments must be of the same type. Very useful for chaining functions together. The ' version is strict

> reduce, reduce' :: (a -> a -> a) -> [a] -> a
> t18  = reduce (>)   [(2*), (1+)] 3 -- is 7  (2*3 + 1)
> t19  = reduce (<<<) [(2*), (1+)] 3 -- is 8 (1+3) * 2

inject and inject\' is foldl with the arguments flipped

> inject, inject' :: (Foldable t) => a -> (a -> b -> a) -> t b -> a  
> t20 = [2,3].inject 1 (-) -- is -4 (1-2-3)

none_of takes a predicate (function a -> Bool) and a list and returns True if none of the elements of the list satisfy the predicate.

>none_of :: (a -> Bool) -> [a] -> Bool  
> t21 = [1..5].none_of (==6) -- is True

select and reject filter those that match, and filter those that don't match.

> select, reject :: (a -> Bool) -> [a] -> [a]  
> t22 = [1..5].reject even -- is [1,3,5]
> t23 = [1..5].select odd  -- is [1,3,5]

inner_map maps a function over the each element of an inner list

> inner_map :: (a -> b) -> [[a]] -> [[b]]  
> t24 = inner_map succ hamlet  -- is ["3","c","ps","opu","up","cf"]

inner_reduce maps reduce over an inner list

> inner_reduce :: (a -> a -> a) -> [[a]] -> [a]  
> t25 = inner_reduce (+) [[1..5].select odd, [1..5].select even]  -- is [9,6]

inner_inject maps inject from above over an inner list

> inner_inject :: (Foldable t) => a -> (a -> b -> a) -> [t b] -> [a]  
> t26 = inner_inject 1 (-) [[1..5].select odd, [1..5].select even] -- is [-8,-5]

label_by takes a function and a list, and returns a list of tuples where the first element of the tuple is f applied to the element of the list, and the second element is the original element. This is an easy way of zipping f of a list with itself.

> label_by :: (a -> c) -> [a] -> [(c, a)]  
> t27 =  hamlet.label_by length .take 3 -- is [(1,"2"),(1,"b"),(2,"or")]

labeling is label_by, with the label coming first

> labeling :: (a -> c) -> [a] -> [(a, c)]  
> t28 = hamlet.labeling length .take 3 -- is [("2",1),("b",1),("or",2)]

in_group_of turns a list into a list of lists where the length of each inner list is given by an Int. The length of the last element of the inner list may be less than the Int.

> in_group_of :: Int -> [t] -> [[t]]  
> t29 = join " " hamlet.in_group_of 3   -- is ["2 b"," or"," no","t t","o b","e"]

split_to turns a list into a list of lists where the number of sublists is given by an Int. If the length of the original list is not divisible by the Int, there will be an additional element.

> split_to :: Int -> [a] -> [[a]]  
> t30 = join " " hamlet.split_to 3  -- is ["2 b o","r not"," to b","e"]

belongs_to and has are like elem with different arugments.

> belongs_to :: (Foldable t, Eq a) => t a -> a -> Bool  
> has :: (Foldable t, Eq b) => b -> t b -> Bool  
> t31 = "not".belongs_to hamlet -- is True
> t32 = hamlet.has "not" -- is True

indexed takes a list and returns a list of tuples, the first element of the tuple being the 0 based index of the position in the list.

> indexed :: (Num t, Enum t) => [b] -> [(t, b)]  
> t33 = hamlet.indexed -- is [(0,"2"),(1,"b"),(2,"or"),(3,"not"),(4,"to"),(5,"be")]

map_with_index first indexes a list, and then applies a map to the result. This makes it easy to manipulate each element of a list based on its position.

> map_with_index :: (Num t, Enum i) => ((i, a) -> b) -> [a] -> [b]  
> t34 = hamlet.map_with_index (\(x,y) -> if x.even  then y.upper else y)
> -- is ["2","b","OR","not","TO","be"]

ljust and rjust left or right justify a string to a fixed length.

> ljust, rjust :: Int -> a -> [a] -> [a]
> t35 = "12".rjust 5 '0'  -- is "00012"
> t36 = "12".ljust 5 '0'  -- is "12000"

swap exchanges the two elements of a two-tuple

> swap :: (a, b) -> (b, a)  
> t37 = swap (2 , "be") -- is ("be",2)

only_fst and only_snd retrieves only the first or second element of a list of tuples

> only_fst :: [(a, b)] -> [a]  
> only_snd :: [(a, b)] -> [b]  
> t38 = only_fst (zip hamlet [1..]) -- is ["2","b","or","not","to","be"]
> t39 = only_snd (zip hamlet [1..]) -- is [1,2,3,4,5,6]

map_fst and map_snd maps a function over only the first or second element of a list of tuples

> map_fst :: (a -> b) -> [(a, c)] -> [(b, c)]  
> map_snd :: (a -> b) -> [(c, a)] -> [(c, b)]
> t40 = map_fst same (zip hamlet [1..3]) -- is [(True,1),(True,2),(False,3)]
> t41 = map_snd (1+) (zip hamlet [1..3]) -- is [("2",2),("b",3),("or",4)]

filter_fst and filter_snd filters a list of tuples by looking only at the fst or snd element of each pair.

> filter_fst :: (a -> Bool) -> [(a, b)] -> [(a, b)]  
> filter_snd :: (b -> Bool) -> [(a, b)] -> [(a, b)]  
> t42 = filter_fst even (zip [1..] hamlet) -- is [(2,"b"),(4,"not"),(6,"be")]

lower upper and capitalize convert a string to lower or upper case

> lower, upper, capitalize :: String -> String  
> t43 = map capitalize hamlet. join " "    -- is "2 B Or Not To Be"
> t44 = map capitalize > join " " $ hamlet -- is "2 B Or Not To Be"
This file is also available as an lhs file if you want to play with it.

Quote of the day:
If your dog is fat, you aren't getting enough exercise.
Unknown

Sitemap
Go up to Haskell Go up to Home Page of Nadine Loves Henry
Go back to Converting from MySQL to CouchDB with Haskell Continue with Understanding Function Composition