packages feed

Craft3e-0.1.0.4: Chapter15/Solutions15.hs

------------------------------------------------------------------------------
--
-- 	Haskell: The Craft of Functional Programming
-- 	Simon Thompson
-- 	(c) Addison-Wesley, 2011.
-- 
-- 	Solutions15
--
------------------------------------------------------------------------------

module Solutions15 where

import Types

--
-- Solution 15.1
--

-- It is always possible to limit what is imported from a particular
-- module through import controls, but that doesn't prevent a client of 
-- the imported module importing anything from the client, if no export
-- controls are in place.

-- On the other hand, export controls are needed for re-export of imported
-- definitions, which are not re-exported by default.

-- Export controls have an annoying limitation: it's not possible to hide
-- particular bindings explicitly on export, rather have to have a whole export
-- list which excludes the binding(s) in question, but which has to include
-- everything else.

--
-- Solution 15.2
--

-- It's the right default: can always re-export, but if everything re-exported a
-- automatically it's harder to look at a module and see where the definitions it 
-- uses come from. As it stands, a definition will be in one of the modules included,
-- or explicitly re-exported from one of those.

-- Also auto re-export would possibly pollute the name space with bindings we don't
-- want to be aware of.

--
-- Solution 15.3
--

-- More brevity. Why not? Could have to check consistency: what if we say "no Dog"
-- but something imported from Dog is explicitly exported?

--
-- Solution 15.4
--

-- LRLRRRRRLRR

--
-- Solution 15.5
--

-- babbat

-- would expect that the shortest is with b coded by a single letter; using the
-- tree in 15.4 get the coding LRLLLRLRR: 9 chars rather than 10.

--
-- Solutions 15.6-7
--

-- Just walk through the definitions

--
-- Solution 15.8
--

mergeSort :: Ord a => [a] -> [a]

mergeSort [] = []

mergeSort [x] = [x]

mergeSort xs 
  = mergeOrd (mergeSort left) (mergeSort right) 
    where
    (left,right) = splitAt (length xs `div` 2) xs

mergeOrd :: Ord a => [a] -> [a] -> [a]

mergeOrd [] ys = ys
mergeOrd xs [] = xs
mergeOrd (x:xs) (y:ys)
  | x<y        = x : mergeOrd xs (y:ys)
  | x==y       = x:y: mergeOrd xs ys
  | otherwise  = y : mergeOrd (x:xs) ys

--
-- Solution 15.9
--

-- change the line
--          | x==y       = x:y: mergeOrd xs ys
-- to
--          | x==y       = x: mergeOrd xs ys

--
-- Solution 15.10
--

-- assuming that x `f` y iff x<=y.

mergeSort' :: (a -> a -> Bool) -> [a] -> [a]

mergeSort' _ [] = []

mergeSort' _ [x] = [x]

mergeSort' f xs 
  = mergeOrd' f (mergeSort' f left) (mergeSort' f right) 
    where
    (left,right) = splitAt (length xs `div` 2) xs

mergeOrd' ::  (a -> a -> Bool) -> [a] -> [a] -> [a]

mergeOrd' _ [] ys = ys
mergeOrd' _ xs [] = xs
mergeOrd' f (x:xs) (y:ys)
  | x `f` y        = x : mergeOrd' f xs (y:ys)
  | otherwise      = y : mergeOrd' f (x:xs) ys

--
-- Solution 15.11
--

-- already in MakeTree.hs

--
-- Solution 15.12
--

-- Stadard calculation.

--
-- Solution 15.13
--

-- showTable is a standard layout problem.

showTree :: Tree -> String

showTreeInd :: Int -> Tree -> String

showTree = showTreeInd 0

showTreeInd n (Leaf ch int) = replicate n ' ' ++ show ch ++ ": " ++ show int ++"\n"
showTreeInd n (Node m t1 t2) = showTreeInd (n+4) t1 ++
                               replicate n ' ' ++ show n ++
                               showTreeInd (n+4) t2

--
-- Solution 15.14
--

-- Basic property to expect is that (decode.code) is the identity function, or
--       decode (code string) = string
-- But need the string to come from the elements in the code tree. Alternatively
-- can just left the coding function drop anything unrecodgnised, and then compare
-- the results of decode.code with the string with the unrecognised characters 
-- removed. This means don't have to write a special generator, but means that most
-- of the tests are effectively on the empty list.

--
-- Solution 15.15
--

sorted :: [Int] -> Bool

sorted [] = True
sorted [x] = True
sorted (x:y:zs) = x<=y && sorted (y:zs)

--
-- Solution 15.16
--

-- Pretty open-ended. Note discussion for 15.14 above. Often different ways of
-- solving the same problem.

--
-- Solution 15.17
--

-- an example is given in 15.14.

--
-- Solution 15.18
--

-- It's possible to write a property / test of whether a sequence of L's and R's is
-- a valid code. For the abt tress above, would have LL as a valid code sequence but
-- not LR, as this should be LRL or LRR. Any sequence is a valid initial segment, so 
-- can be extended to a valid code. Once that's done, then should expect that
-- code.decode is also the identity (on that subset).