REVISED: Saturday, February 3, 2024
Haskell Lists.
I. HASKELL NUMERIC AND CHARACTER LISTS
The Data.List module is the home of all standard list functions.
Prelude> :module +Data.List
The Data.List module is the home of all standard list functions.
Prelude> :module +Data.List
Prelude>
Prelude> "U" `isPrefixOf` "USA" -- isPrefixOf function matches at the beginning of a list.
True
it :: Bool
Prelude>
Prelude> "S" `isInfixOf` "USA" -- isInfixOf function matches anywhere in a list.
A list can be of any length.Prelude> "U" `isPrefixOf` "USA" -- isPrefixOf function matches at the beginning of a list.
True
it :: Bool
Prelude>
Prelude> "S" `isInfixOf` "USA" -- isInfixOf function matches anywhere in a list.
True
it :: Bool
Prelude>
Prelude> "A" `isSuffixOf` "USA" -- isSuffixOf function matches at the end of a list.
True
it :: Bool
Prelude>
Prelude> :type isPrefixOf
isPrefixOf :: Eq a => [a] -> [a] -> Bool
Prelude>
Prelude> :type isInfixOf
isInfixOf :: Eq a => [a] -> [a] -> Bool
Prelude>
Prelude> :type isSuffixOf
isSuffixOf :: Eq a => [a] -> [a] -> Bool
Prelude>
Prelude> "A" `isSuffixOf` "USA" -- isSuffixOf function matches at the end of a list.
True
it :: Bool
Prelude>
Prelude> :type isPrefixOf
isPrefixOf :: Eq a => [a] -> [a] -> Bool
Prelude>
Prelude> :type isInfixOf
isInfixOf :: Eq a => [a] -> [a] -> Bool
Prelude>
Prelude> :type isSuffixOf
isSuffixOf :: Eq a => [a] -> [a] -> Bool
Prelude>
In Haskell, lists are what arrays are in most other languages.
[] pronounced "nil" is an empty list.
Prelude> :type []
[] :: [t]
Prelude>
Haskell uses pattern matching to tell the compiler how to process data.
The module shown below has two patterns for the compiler to choose from. The first pattern is myMod [] and the second pattern is myMod (x:xs). The compiler makes a choice between the two patterns based on the contents of the function myMod argument. If the argument is an empty list [] the compiler chooses the myMod [] pattern. If the argument is a singleton list [x] or a list of [xs] the compiler chooses the myMod (x:xs) pattern. By convention, list arguments usually have an s suffix on their name; e.g., [xs] for a list of xs, or [[xss],[]] for a list of lists and so forth.
The function syntax is as follows:
<function name> <function arguments> = <return values>
error is a Prelude function that allows the programmer to code a message to be printed when an exception error occurs. In the module shown below the programmer is telling the compiler that when myMod has the empty list [] as an argument to print the exception error message "Empty list!". The programmer can choose any message to be printed as long as the message in enclosed in double " " marks.
Module:
module MyMod where -- All module names; i.e., MyMod start with a capital letter.
myMod :: [t] -> [t] -- Function signature.
myMod [] = error "Empty list!" -- When argument is an empty list [], prints exception error message.
myMod (x:xs) = xs -- Pattern which returns xs.
GHCi:
Prelude> :load MyMod
[1 of 1] Compiling MyMod ( MyMod.hs, interpreted )
Ok, modules loaded: MyMod.
Prelude>
Prelude> myMod []
*** Exception: Empty list!
Prelude>
Prelude> myMod [1,2,3,4,5,6,7,8,9,10]
[2,3,4,5,6,7,8,9,10] -- Notice the compiler return xs which is the tail of the list.
Prelude>
A singleton pattern is a design pattern that restricts the instantiation of a class to one object.
[a] is a singleton list (a:[]).
Prelude> :t (:[]) -- Rotate (:[]) 90 degrees to the right and you see the head of a robot.
(:[]) :: a -> [a]
Prelude>
Prelude> :type [1,2]
[1,2] :: Num t => [t]
Prelude>
=> reads, "implies". The way to read the above is to say, “t being an instance of Num implies a list [t] of t's.”
Prelude> :type [True,False]
[True,False] :: [Bool]
Prelude>
Prelude> :type [(1,2),(2,3)]
[(1,2),(2,3)] :: (Num t1, Num t) => [(t, t1)]
Prelude>
Prelude> :type [[1,2],[2,3,4]]
[[1,2],[2,3,4]] :: Num t => [[t]]
Prelude>
A. HASKELL LISTS FROM GIVEN ELEMENTS
The value to the left of the :, pronounced "cons" for construct, is placed as the first element of the list. cons is another word for :. In lists, : is actually a constructor that takes a value and another list, and returns a list.
Prelude> :type (:)
(:) :: a -> [a] -> [a]
Prelude>
[1,2,3]
it :: Num a => [a]
Prelude>
We can also use the Prelude foldr function to show an example of the identity function.
Prelude> let myId = foldr (:) []
Prelude>
Prelude> :type myId
myId :: [a] -> [a]
Prelude>
Prelude> myId [1,2,3]
[1,2,3]
it :: Num a => [a]
Prelude>
These examples are really singly-linked lists, and not arrays. Haskell does not have array primitives.
Prelude> 4: 5 : 6 : []
[4,5,6]
it :: Num a => [a]
Prelude>
["1","2","3"]
it :: [[Char]]
Prelude>
Prelude> "4": "5": "6": []
["4","5","6"]Prelude> "4": "5": "6": []
Prelude>
B. COMBINING HASKELL LISTS
Prelude> [1,2,3] ++ [4,5,6] -- ++ is pronounced, "append"; and concatenates two lists.
[1,2,3,4,5,6]
it :: Num a => [a]
Prelude>
["1","2","3","4","5","6"]
it :: [[Char]]
Prelude>
Prelude> :type (++) -- :t is the same as :type.
(++) :: [a] -> [a] -> [a]
Prelude>
["1","2","3","4","5","6"] -- Prelude concat function removes one level of nesting; i.e., the inner square brackets.
it :: [[Char]]
it :: [[Char]]
Prelude>
concat :: [[a]] -> [a]
Prelude>
(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
(x:xs) ++ ys = x : (xs ++ yx)
II. ACCESSING HASKELL SUBLISTS
Strings are lists of characters; therefore, you can use list functions on strings.
A. ACCESSING THE FIRST ELEMENT OF A LIST
To access the first element of a list, we use the Prelude head function.
To access the first element of a list, we use the Prelude head function.
Prelude> :type head
head :: [a] -> a
Prelude>
a is the type variable. We can read the signature as “takes a list, all of whose elements have some type a, and returns a value of the same type a”.
Prelude> let ls = ["1","2","3","4","5","6"] -- ls is immutable, it never changes.
Prelude>
Prelude> head ls -- Returns a new list containing the first list element of ls.
"1"it :: [Char]
Prelude>
head is what is known as a partial function. There are certain inputs, i.e., empty list [], for which head will crash.
Prelude> head []
Functions which have certain inputs that will make them recurse infinitely are also called partial. Functions which are well-defined on all possible inputs are known as total functions. It is good Haskell practice to avoid partial functions. Other partial Prelude functions include tail, init, last, and (!!).
Shown below is the Prelude tail function, which returns all but the head of a list.
Prelude> head []
*** Exception: Prelude.head: empty list -- Calling an exception or an error does not qualify as returning a value!
Prelude>
Functions which have certain inputs that will make them recurse infinitely are also called partial. Functions which are well-defined on all possible inputs are known as total functions. It is good Haskell practice to avoid partial functions. Other partial Prelude functions include tail, init, last, and (!!).
Shown below is the Prelude tail function, which returns all but the head of a list.
Prelude> let ls = ["1","2","3","4","5","6"]
Prelude>
You have to add ls to local memory because when you do the :load MyTail all local memory is erased.
["2","3","4","5","6"] -- Haskell creates a new list; this is not the original ls list.
it :: [[Char]]
Prelude>
Writing your own version of Prelude functions helps you learn Haskell. For example, the following myTail is a version of Prelude Tail.
Module:
module MyTail where -- Module names; e.g., MyTail must always start with capital letter.
myTail :: [t] -> [t] -- Function names; e.g., myTail must always start with lower case letter.
myTail [] = error "Empty list!"
myTail (x:xs) = xs
GHCi:
Prelude> :load MyTail
[1 of 1] Compiling MyTail ( MyTail.hs, interpreted )
Ok, modules loaded: MyTail.
Prelude>
Prelude> let ls = ["1","2","3","4","5","6"]
Prelude>
You have to add ls to local memory because when you do the :load MyTail all local memory is erased.
["2","3","4","5","6"] -- The list returned by myTail function body is a copy of ls.
Prelude>
Prelude> ls
["1","2","3","4","5","6"] -- Original ls is immutable; therefore, does not change.
Prelude>
B. ACCESSING THE LAST ELEMENT OF A LIST
Prelude function last, returns the very last element of a list.
Prelude> :type last
last :: [a] -> a
Prelude>
Prelude> last ls
"6"it :: [Char]
Prelude>
Prelude> ls
["1","2","3","4","5","6"] -- ls is immutable; therefore, ls does not change.
Prelude>
Module:
module MyLast where
myLast :: [t] -> t
myLast [] = error "Empty list!"
myLast [x] = x
myLast (x:xs) = myLast xs
GHCi:
Prelude> :load MyLast
[1 of 1] Compiling MyLast ( MyLast.hs, interpreted )
Ok, modules loaded: MyLast.
Prelude>
Prelude> let ls = ["1","2","3","4","5","6"]
Prelude>
Prelude> myLast ls
"6"
Prelude>
C. ACCESSING AN ELEMENT AT A GIVEN INDEX
If you want to get an element out of a list by index, use !! pronounced index.
(!!) :: [a] -> Int -> a
Prelude>
Prelude>
Prelude> ["1","2","3","4","5","6"] !! 3
"4"
Prelude>
There are both "zero based indexes" and "one based indexes". Zero based indexes start with zero. One based indexes start with one. Haskell uses zero based indexes for lists. Therefore, in our example above; index 0 would return 1, index 1 would return 2, index 2 would return 3, and index 3 would return 4.
D. ACCESSING THE FIRST N ELEMENTS
Prelude> :type take
take :: Int -> [a] -> [a]
Prelude>
The -> is right associative; therefore, take gives type Int to a function.
take :: Int -> ([a] -> [a])
The function take takes one argument, an Int, and returns another function ([a] -> [a]). That other function also takes one argument, a list [a] , and returns a list [a] of the same type as its result.
The take function has two arguments: an integer n, and a list ls; and produces the first n elements of ls. By convention a list is written ls and a list of lists would be written lss each list argument with a s suffix.
The take function has two arguments: an integer n, and a list ls; and produces the first n elements of ls. By convention a list is written ls and a list of lists would be written lss each list argument with a s suffix.
["1","2","3","4"]
it :: [[Char]]
Prelude>
Prelude> takeWhile (<= 5) [1..]
[1,2,3,4,5]
Prelude>
Module:
module MyTake where
myTake :: (Ord a, Num a) => a -> [t] -> [t]
myTake n _
| n <= 0 = [] -- Checking for negative numbers.
myTake _ [] = [] -- Checking for empty list.
myTake n (x:xs) = x:myTake (n-1) xs -- Checking all other cases.
GHCi:
Prelude> :load MyTake
[1 of 1] Compiling MyTake ( MyTake.hs, interpreted )
Ok, modules loaded: MyTake.
Prelude>
Prelude> myTake (-5) [1,2,3,4,5,6]
[]
Prelude>
Prelude> myTake 5 []
[]
Prelude>
Prelude> myTake 5 [1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5]
Prelude>
E. ACCESSING THE LAST N ELEMENTS
Prelude> :type reverse
reverse :: [a] -> [a]
Prelude>
["3","4","5","6"]
it :: [[Char]]
Prelude>
The dot . is the function composition operator, dot is read as, "after". The dot . operator has very high precedence, surpassed only by function application.
Function composition is the act of pipelining the result of one function, to the input of another, creating an entirely new function. This can be done with any two functions, where the argument type of the first is the return type of the second.
$ is pronounced, "apply". When a $ is encountered, the expression on its right is applied as the parameter to the function on its left.
F. ACCESSING THE N ELEMENTS STARTING FROM INDEX M
Prelude> :type drop
drop :: Int -> [a] -> [a]
Prelude>
["2","3","4","5"]
it :: [[Char]]
Prelude>
module Drop where
drop :: Int -> [a] -> [a]
drop 0 xs = xs
drop (n+1) [] = []
drop (n+1) (_:xs) = drop n xs
G. SPLITTING A STRING INTO A LIST OF WORDS
Prelude> :type words
words :: String -> [String]
Prelude>
["Mary","had","a","little","lamb."]
it :: [String]
Prelude>
Prelude> unwords ["Mary","had","a","little","lamb."]
"Mary had a little lamb."
Prelude>
H. SPLITTING A LIST INTO TWO PARTS
Prelude> :type splitAt
splitAt :: Int -> [a] -> ([a], [a])
Prelude>
("abcdefghijkl","mnopqrstuvwxyz")
Prelude>
Prelude> splitAt 12 ['a'..'z']
("abcdefghijkl","mnopqrstuvwxyz")
Prelude>
I. LENGTH OF A LIST
The length function tells us how many elements are in a list.
The length function tells us how many elements are in a list.
Prelude> :type length
length :: [a] -> Int
Prelude>
Prelude> length "abcdefghijklmnopqrstuvwxyz"
26Prelude> length ['a'..'z']
26
Prelude>length [1..10]
10
Prelude>
module Length where
length :: [a] -> Int
length [] = 0
length (_:xs) = 1 + length xs
{-
length maps the empty list to 0, and any non-empty list to
the successor of the length of its tail.
-}
Prelude> :{
Prelude| len [] = 0
Prelude| len (_:xs) = 1 + len xs
Prelude| :}
Prelude> len [1,2,3,4,5,6,7,8,9,10]
10
Prelude>
Prelude> let myLength = sum . map (\_ -> 1)
Prelude> myLength [1,2,3,4]
4
J. REVERSE A LIST
Prelude> :type reverse
reverse :: [a] -> [a]
Prelude>
Prelude> reverse [1,2,3]
[3,2,1]
it :: Num a => [a]
Prelude>
it :: Num a => [a]
Prelude>
module Reverse where
reverse :: [a] -> [a]
reverse [] = []
reverse (x:xs) = reverse xs ++ [x]
{-
reverse maps the empty list to the empty list
and any non-empty list to the reverse of its tail
appended to its head.
-}
The process of interpreting code by substituting equals-for-equals is known as equational reasoning. For example, with equational reasoning we can compute the reverse of 1, 2, 3 as follows:
reverse [1,2,3]
=
reverse [2,3] ++ [1]
=
(reverse [3] ++ [2]) ++ [1]
=
((reverse [] ++ [3]) ++ [2]) ++ [1]
=
(([] ++ [3]) ++ [2]) ++ [1]
=
[3,2,1]
K. APPLY A FUNCTION TO EACH ELEMENT IN A LIST
The higher-order library function called map applies a function; for example, (5*) to every element of a list.
Prelude> :type map
map :: (a -> b) -> [a] -> [b]
Prelude>
[5, 10, 15, 20, 25, 30]
it :: Num b => [b]
Prelude>
Using (5*) is called sectioning notation which is the same as using an anonymous function fiveX = \x -> x * 5.
Prelude> let fiveX = \x -> x * 5
Prelude>
Prelude> fiveX 2
10
Prelude>
Prelude> :type fiveX
fiveX :: Num a => a -> a
Prelude>
The map function defined using list comprehension:
map f xs = [f x | x <- xs]
The map function defined using recursion:
map f [] = []
map f (x:xs) = f x : map f xs
L. FILTER A LIST
Prelude> :type filter
filter :: (a -> Bool) -> [a] -> [a]
Prelude>
filter cannot add elements; it can only remove them. When we filter we are choosing whether to keep an element of a list, depending on whether or not a particular predicate holds. A predicate is a function of type Int -> Bool which returns True for those elements which should be kept, and False for those which should be discarded.
filter returns a list constructed from members of a list, the second argument, fulfilling a condition given by the predicate, the first argument.
Prelude> filter (>5) [1, 2, 3, 4, 5, 6, 7, 8]
[6, 7, 8]
it :: (Ord a, Num a) => [a]
Prelude>
Filter defined using list comprehension:
filter p xs = [x | x <- xs, p x]
Filter defined using recursion:
filter p [] = []
filter p (x:xs)
| p x = x : filter p xs
| otherwise = filter p xs
M. FOLD A LIST
Any function that traverse a list from left to right or right to left, one element by element, and accumulates a result, can be implemented with a fold.
Prelude> :type foldl
foldl :: (b -> a -> b) -> b -> [a] -> b
Prelude>
foldl takes a function which turns a b and a b into a b, an initial value of type b and a list of as. It produces a b.
Prelude> :type foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
Prelude>
Prelude>
sum = foldr (+) 0
product = foldr (*) 1
or = foldr (||) False
and = foldr (&&) True
Foldr defined using recursion and the above notation:
f = (+)
v = 0
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f v [] = v
foldr f v (x:xs) = f x (foldr f v xs)
The compiler is able to turn most recursions into loops. This is called tail recursion optimization, where the recursive call at the very end of a function is simply turned into a goto to the beginning of the function.
Prelude> import Data.Foldable
Prelude> Data.Foldable.foldl (+) 0 [1..5] -- Zero indexed, 0 starting point.
15
it :: (Num a, Enum a) => a
Prelude>
This is the same as:
0 + 1 + 2 + 3 + 4 + 5
which equals 15.
This is the same as:
sum2 :: Num a => [a] -> a
sum2 [] = 0
sum2 (x:xs) = x + sum2 xs
Prelude> :load sum2
[1 of 1] Compiling Main ( sum2.hs, interpreted )
Ok, modules loaded: Main.
Prelude>
Prelude> sum2 [0,1,2,3,4,5]
15
Prelude>
sum2 [0,1,2,3,4,5]
=
foldr (+) 0 [0,1,2,3,4,5]
=
foldr (+) 0 (0:(1:(2:(3:(4:(5:[])))))) -- fold right
=
0+(1+(2+(3+(4+(5+0)))))
=
6
N. ZIP A LIST
As shown below zip transposes a pair of lists ([a] , [b]) into a list of pairs [(a, b)] :
zip :: [a] -> [b] -> [(a, b)]
Prelude>
The library function zip produces a new list by pairing successive elements from two existing lists until either or both are exhausted.
[(1,9),(2,8),(3,7)]
it :: (Num b, Num a) => [(a, b)]
Prelude>
Module:
module MyZip where
myZip :: [a] -> [b] -> [(a,b)] -- Function signature.
myZip [] _ = [] -- [a] becomes empty first.
myZip _ [] = [] -- [b] becomes empty first.
myZip (x:xs) (y:ys) = (x,y) : myZip xs ys
GHCi:
Prelude> :load MyZip
[1 of 1] Compiling MyZip ( MyZip.hs, interpreted )
Ok, modules loaded: MyZip.
Prelude>
Prelude> let ls1 = ["1", "2", "3"]
Prelude>
Prelude> let ls2 = ["4", "5", "6"]
Prelude>
Prelude> myZip ls1 ls2
[("1","4"),("2","5"),("3","6")]
Prelude>
O. ZIPWITH A LIST
Prelude> :type zipWith
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
Prelude>
zipWith makes a list whose elements are calculated from a function and the elements of input lists occurring at the same position in both lists.
Prelude> zipWith (+) [1,2,3] [3,2,1]
[4,4,4]it :: Num c => [c]
Prelude>
P. liftM
Prelude> import Control.Monad
Prelude>
liftM promotes a function to a monad.
Prelude> :type liftM
liftM :: Monad m => (a1 -> r) -> m a1 -> m r
Prelude>
Prelude>
"Copy Paste" the following script into your text editor, and "File, Save As" MaryTxtFile.txt in your working directory.
Mary had a little lamb,
its fleas were white as snow.
And everywhere that Mary went,
its fleas were sure to go.
Prelude> :cd C:\Users\Tinnel\Haskell2024\
Prelude>
Prelude> liftM lines (readFile "MaryTxtFile.txt")
["Mary had a little lamb,","its fleas were white as snow.","And everywhere that Mary went,","its fleas were sure to go."]
it :: [String]
Prelude>
Lists can be compared if the elements within the lists can be compared. When using <, <=, >, and >= to compare lists, they are compared in lexicographical order. First the heads are compared. If they are equal then the second elements are compared, etc.
R. LIST COMPREHENSIONS
Let S be a set, ∀ be for every, ∈ be is an element of, and p(x) be a predicate.
Mathematically we can write the following statement.
∀x∈S, p(x)
For every x such that x is an element of the set S and satisfies the predicate p(x).
In Haskell <- is pronounced "drawn from" and p x is called a condition, or "predicate".
Below, the function x which satisfies the predicate x+5 is drawn from the set [1,2,3].
Prelude> [ x+5 | x <- [1,2,3] ]
[6,7,8]
it :: Num t => [t]
Prelude>
Prelude> [ x | x <- [2..10], 10 `mod` x == 0]
[2,5,10]
Prelude>
Prelude> [ team ++ " " ++ player |
team <- ["red", "blue"],
player <- ["soldier", "pyro", "scout"] ] -- Surprised? Try it.
["red soldier","red pyro","red scout","blue soldier","blue pyro","blue scout"]
it :: [[Char]]
Prelude>
The following is accepted by Prelude as shown above because it is one single line of code:
[ team ++ " " ++ player | team <- ["red", "blue"], player <- ["soldier", "pyro", "scout"] ]
List comprehensions are used for building more specific lists out of general lists.
S is a set.
∈ is an element of.
ℕ is a set of all natural numbers.
S = { x * 3 | x ∈ ℕ, (x * 3) ≦ 51 }
Prelude> [x*3 | x <- [0..], x*3 <= 51]
[0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51Interrupted.
Prelude>
In the example above GHCi will stop processing at 51. There is a tool bar at the top of the GHCi window. Select Actions in the GHCi tool bar, and then select Stop; or press Ctrl+C to interrupt processing and to return to the Prelude> prompt.
S = { x * 3 | x ∈ [12..20], (x * 3) ≦ 51 }
Prelude> [x*3 | x <- [12..20], x*3 <= 51]
[36,39,42,45,48,51]
it :: (Ord t, Num t, Enum t) => [t]
Prelude>
The part before the pipe |, is the output function x*3. x is drawn from the input set of 12 to 20. For every element in 12..20 that we have bound to x we get that element x multiplied by 3 if it satisfies the condition, predicate, of being <= 51.
List comprehensions are an expressive shorthand for building computations on lists.
S. LIST DIFFERENCE \\ OPERATOR
Prelude> :type (\\)
(\\) :: Eq a => [a] -> [a] -> [a]
Prelude>
Prelude>
The list difference \\ operator takes two lists, goes through the second and for each item, removes the first instance of the same item from the first list.
Prelude>
Prelude> [1..10] \\ [2, 3, 5, 8]
[1,4,6,7,9,10]
it :: (Num a, Eq a, Enum a) => [a]
Prelude>
[1, 2,3,4,5,6,7,8,9,10] -- First list [1..10].
[ 2,3, 5, 8 ] -- Second list.
[1, 4, 6,7, 9,10]
T. NUB
Prelude> :type nub
nub :: Eq a => [a] -> [a]
Prelude>
Prelude> import Data.List
Prelude>
Prelude> nub [1,1,2,2,3,3,4,4,5,5]
[1,2,3,4,5]
Prelude>
U. INIT
Prelude> :type init
Prelude> :info init
Prelude> init "hello"
T. NUB
nub
, eliminates all duplicate elements from a list.Prelude> :type nub
nub :: Eq a => [a] -> [a]
Prelude>
Prelude> import Data.List
Prelude>
Prelude> nub [1,1,2,2,3,3,4,4,5,5]
[1,2,3,4,5]
Prelude>
U. INIT
init
, returns a list of all but the last element of its input.Prelude> :type init
init :: [a] -> [a]
Prelude>Prelude> :info init
init :: [a] -> [a] -- Defined in `GHC.List'
Prelude>Prelude> init "hello"
"hell"
it :: [Char]
Prelude>
Module:
module MyInit where
myInit :: [t] -> [t]
myInit [] = error "Empty list!"
myInit [_] = []
myInit (x:xs) = x:myInit xs
GHCi:
Prelude> :load MyInit
[1 of 1] Compiling MyInit ( MyInit.hs, interpreted )
Ok, modules loaded: MyInit.
Prelude> let ls = ["1","2","3","4","5","6"]
Prelude>
Prelude> myInit ls
["1","2","3","4","5"]
Prelude>
Prelude> myInit ["1"]
[]
Prelude>
Prelude> myInit []
*** Exception: Empty list!
Prelude>
V. ELEM
elem is the list membership predicate, usually written in infix form, e.g., x `elem` xs.
Prelude> :type elem
elem :: Eq a => a -> [a] -> Bool
Prelude>
Prelude> 5 `elem` [1,2,3,4,5] -- Infix uses backticks ` not apostrophes '.
True
Prelude>
Module:
module MyElem where
myElem :: Eq a => a -> [a] -> Bool
myElem _ [] = False
myElem e (x:xs)
| e == x = True
| otherwise = myElem e xs
GHCi:
Prelude> :load MyElem
[1 of 1] Compiling MyElem ( MyElem.hs, interpreted )
Ok, modules loaded: MyElem.
Prelude>
Prelude> myElem 5 [1,2,3,4,5]
True
Prelude>
Prelude> myElem 5 [1,2,3,4]
False
Prelude>
W. SORT
sort sorts a list.
Prelude> :type sort
sort :: Ord a => [a] -> [a]
Prelude>
Prelude> sort [4,3,6,9,1,2]
[1,2,3,4,6,9]
Prelude>
X. PRODUCT
Prelude> product [4,3,6,9,1,2]
X. PRODUCT
Prelude> product [4,3,6,9,1,2]
1296
Prelude>
Prelude>
III. CONCLUSION
In this tutorial, you have received an introduction to Haskell lists.
IV. REFERENCES
Bird, R. (2015). Thinking Functionally with Haskell. Cambridge, England: Cambridge University Press.
Davie, A. (1992). Introduction to Functional Programming Systems Using Haskell. Cambridge, England: Cambridge University Press.
Goerzen, J. & O'Sullivan, B. & Stewart, D. (2008). Real World Haskell. Sebastopol, CA: O'Reilly Media, Inc.
Hutton, G. (2007). Programming in Haskell. New York: Cambridge University Press.
Lipovača, M. (2011). Learn You a Haskell for Great Good!: A Beginner's Guide. San Francisco, CA: No Starch Press, Inc.
Thompson, S. (2011). The Craft of Functional Programming. Edinburgh Gate, Harlow, England: Pearson Education Limited.