| Login |
|
| ||||
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"
The raw lhs file is available for you to play with if you are so inclined. You can also read this page in pdf format Please address any complaints, comments, or misc. personal abuse to Henry Laxen Thanks.
