-- Returns true if the first sequence of items appears anywhere in the -- second list. The sequence either appears at the front of the list, -- or it appears in its entirety somewhere in the tail of the list. subsequence [] _ = True -- [] is subsequence of anything subsequence _ [] = False -- Can't find a subsequence in [] subsequence seq (y:ys) = take (length seq) (y:ys) == seq || subsequence seq ys -- A crude way to tell if two functions are the same. Compares their -- results on a range of integer inputs and returns true if both functions -- agree for each input value in the range. We have to use an explicit -- type signature to restrict the range endpoints to be integers. same_output :: Integral a => (a -> a) -> (a -> a) -> a -> a -> Bool same_output fn1 fn2 low high = (map fn1 inputs) == (map fn2 inputs) where inputs = [low..high] -- Takes a one-argument function and returns a "loud" version of it that -- returns a string when applied to an input. The string contains both -- the input passed to the function and the output value. make_loud_version fn = \input -> "fn (" ++ show input ++ ") --> " ++ show (fn input) -- Generate "words" that can be formed by the letters associated with -- a phone number. If it's not a base case, make a recursive call to -- generate the words produced by the tail of the number, then produce -- a new group of longer words by tacking on the letters associated with -- the first number, in turn. This requires a nested map expression: -- the inner map works over the letters associated with the first number -- in the list, and the outer map feeds it words from the recursive call. phone_spell :: [Int] -> [[Char]] phone_spell [] = [] phone_spell [n] = letters n phone_spell (n:ns) = concat word_groups where new_letters = letters n -- List of letters on button n rest_spell = phone_spell ns -- Words formed by nums in ns word_groups = map (\word -> map (++word) new_letters) rest_spell letters n = case n of 2 -> ["a", "b", "c"] 3 -> ["d", "e", "f"] 4 -> ["g", "h", "i"] 5 -> ["j", "k", "l"] 6 -> ["m", "n", "o"] 7 -> ["p", "q", "r", "s"] 8 -> ["t", "u", "v"] 9 -> ["w", "x", "y", "z"] _ -> [""] -- Nifty version that uses a list comprehension with multiple -- generators to "mix" the pieces! phone_spell2 [] = [] phone_spell2 [n] = letters n phone_spell2 (n:ns) = [ a ++ b | a <- letters n, b <- phone_spell2 ns]