-- ghc -O2 -fspec-constr-recursive=10 -fmax-worker-args=16 -- Convert the input file to camel case and write to stdout import Data.Function ((&)) import Data.Word (Word8) import System.Environment (getArgs) import System.IO (Handle, IOMode(..), openFile, stdout) import qualified Streamly.Prelude as Stream import qualified Streamly.FileSystem.Handle as Handle -- | @camelCase source-file dest-file@ camelCase :: Handle -> Handle -> IO () camelCase src dst = Stream.unfold Handle.read src -- SerialT IO Word8 & Stream.scanl' step (True, Nothing) -- SerialT IO (Bool, Maybe Word8) & Stream.mapMaybe snd -- SerialT IO Word8 & Stream.fold (Handle.write dst) -- IO () where isNewline x = x == 0x0a isUpper x = x >= 0x41 && x <= 0x5a isLower x = x >= 0x61 && x <= 0x7a -- Scan accumulator @(wasSpace, output)@ contains whether the previous -- character was white space, and if the current char should be emitted in -- the output. step :: (Bool, Maybe Word8) -> Word8 -> (Bool, Maybe Word8) step (wasSpace, _) x -- Newline or upper case chars go unmodified | isNewline x || isUpper x = (False, Just x) -- Convert lower to upper if preceded by whitespace | isLower x = (False, Just $ if wasSpace then x - 32 else x) | otherwise = (True, Nothing) main :: IO () main = do name <- fmap head getArgs src <- openFile name ReadMode camelCase src stdout