module Refactor where import Prelude hiding (Maybe(..), maybe, intersperse) -- -- * Systematic generalization -- -- | Insert the string ", " between words in a list of words. commas :: [String] -> [String] commas [] = [] commas [w] = [w] commas (w:ws) = w : ", " : commas ws -- | Insert the string "; " between words in a list of words. semis :: [String] -> [String] semis [] = [] semis [w] = [w] semis (w:ws) = w : "; " : semis ws -- ** Introduce parameters for constants seps :: String -> [String] -> [String] seps s [] = [] seps s [w] = [w] seps s (w:ws) = w : s : seps s ws commas' = seps ", " semis' = seps "; " -- ** Broaden the types intersperse :: a -> [a] -> [a] intersperse s [] = [] intersperse s [x] = [x] intersperse s (x:xs) = x : s : intersperse s xs commas'' = intersperse ", " semis'' = intersperse "; " zeros = intersperse 0 -- -- * Abstracting repeated programming patterns -- data Maybe a = Nothing | Just a deriving (Eq,Show) -- ** Inside a calculator app -- | Convert a floating point result to a string, -- or return "ERROR" if on an error (Nothing). showResult :: Maybe Float -> String showResult Nothing = "ERROR" showResult (Just x) = show x -- | Add a value to another value that may have failed. -- Interpret an error (Nothing) as zero. safeAdd :: Int -> Maybe Int -> Int safeAdd x Nothing = x safeAdd x (Just y) = x + y -- ** Inside a robot app -- | Directions. data Dir = N | S | E | W deriving (Eq,Show) -- | Robot commands. data Command = Move Dir | FireLaser Dir | SelfDestruct | Stay deriving (Eq,Show) -- | Move in some direction, or stay if no direction is provided. moveCommand :: Maybe Dir -> Command moveCommand Nothing = Stay moveCommand (Just d) = Move d -- ** Abstract out common pattern maybe :: b -> (a -> b) -> Maybe a -> b maybe y f Nothing = y maybe y f (Just x) = f x showResult' = maybe "ERROR" show safeAdd' x = maybe x (x+) moveCommand' = maybe Stay Move