Difference between revisions of "H99: NinetyNine Haskell Problems"
m 

Line 149:  Line 149:  
If a list contains repeated elements they should be replaced with a single copy of the element. The order of the elements should not be changed. 
If a list contains repeated elements they should be replaced with a single copy of the element. The order of the elements should not be changed. 

−  +  Example: 

−  +  * (compress '(a a a a b c c a a d e e e e)) 

−  +  (A B C A D E) 

</pre> 
</pre> 

−  +  Example in Haskell: 

−  +  *Main> compress ['a','a','a','a','b','c','c','a','a','d','e','e','e','e'] 

−  +  ['a','b','c','a','d','e'] 

<haskell> 
<haskell> 

Line 162:  Line 162:  
</haskell> 
</haskell> 

−  +  We simply group equal values together (group), then take the head of each. 

−  +  
[[Category:Tutorials]] 
[[Category:Tutorials]] 
Revision as of 05:45, 12 December 2006
These are Haskell translations of Ninety Nine Lisp Problems.
Contents
Problem 1
(*) Find the last box of a list. Example: * (mylast '(a b c d)) (D)
This is "last" in Prelude, which is defined as:
last :: [a] > a
last [x] = x
last (_:xs) = last xs
Problem 2
(*) Find the last but one box of a list. Example: * (mybutlast '(a b c d)) (C D)
This can be done by dropping all but the last two elements of a list:
myButLast :: [a] > [a]
myButLast list = drop ((length list)  2) list
Problem 3
(*) Find the K'th element of a list. The first element in the list is number 1. Example: * (elementat '(a b c d e) 3) C
This is (almost) the infix operator !! in Prelude, which is defined as:
(!!) :: [a] > Int > a
(x:_) !! 0 = x
(_:xs) !! n = xs !! (n1)
Except this doesn't quite work, because !! is zeroindexed, and elementat should be oneindexed. So:
elementAt :: [a] > Int > a
elementAt list i = list !! (i1)
Problem 4
(*) Find the number of elements of a list.
This is "length" in Prelude, which is defined as:
length :: [a] > Int
length [] = 0
length (_:l) = 1 + length l
Problem 5
(*) Reverse a list.
This is "reverse" in Prelude, which is defined as:
reverse :: [a] > [a]
reverse = foldl (flip (:)) []
The standard definition is concise, but not very readable. Another way to define reverse is:
reverse :: [a] > [a]
reverse [] = []
reverse (x:xs) = reverse xs ++ [x]
Problem 6
(*) Find out whether a list is a palindrome. A palindrome can be read forward or backward; e.g. (x a m a x).
This is trivial, because we can use reverse:
isPalindrome :: (Eq a) => [a] > Bool
isPalindrome xs = xs == (reverse xs)
Problem 7
(**) Flatten a nested list structure. Transform a list, possibly holding lists as elements into a `flat' list by replacing each list with its elements (recursively). Example: * (myflatten '(a (b (c d) e))) (A B C D E)
This is tricky, because lists in Haskell are homogeneous. [1, [2, [3, 4], 5]] is a type error. We have to devise some way of represent a list that may (or may not) be nested:
data NestedList a = Elem a  List [NestedList a]
flatten :: NestedList a > [a]
flatten (Elem x) = [x]
flatten (List []) = []
flatten (List (x:xs)) = flatten x ++ flatten (List xs)
Our NestedList datatype is either a single element of some type (Elem a), or a list of NestedLists of the same type. (List [NestedList a]). Let's try it out in ghci:
*Main> flatten (Elem 5) [5] *Main> flatten (List [Elem 1, List [Elem 2, List [Elem 3, Elem 4], Elem 5]]) [1,2,3,4,5] *Main> flatten (List []) []
Problem 8
(**) Eliminate consecutive duplicates of list elements. If a list contains repeated elements they should be replaced with a single copy of the element. The order of the elements should not be changed. Example: * (compress '(a a a a b c c a a d e e e e)) (A B C A D E)
Example in Haskell:
 Main> compress ['a','a','a','a','b','c','c','a','a','d','e','e','e','e']
['a','b','c','a','d','e']
compress = map head . group
We simply group equal values together (group), then take the head of each.