[Haskell-cafe] minor refactoring problem

Stefan Holdermans stefan at vectorfabrics.com
Tue Nov 29 09:35:13 CET 2011


Martin,

> importFile :: Editor -> String -> IO ()
> importFile ed path = do
>  s <- readFile path
>  ps <- mapM (\x -> makePair (x, "")) (lines s)
>  es <- return $ V.fromList ps
>  writeIORef ed es
> 
> loadFile :: Editor -> String -> IO ()
> loadFile ed path = do
>  s <- readFile path
>  ps <- mapM makePair (parseFile s)
>  es <- return $ V.fromList ps
>  writeIORef ed es

> The problem is that loadFile and importFile are so similar it seems a
> shame not to combine them somehow, but anything I can think of doing
> leaves the code looking more rather than less messy. Any nice ideas?

Have you considered abstracting over the bits in which importFile and loadFile differ? For example:

  processFile :: (String -> IO [PairBox]) -> Editor -> String -> IO ()
  processFile f ed path = do
    s <- readFile path
    ps <- f s
    es <- return $ V.fromList ps
    writeIORef ed es

  importFile = processFile (mapM (\x -> makePair (x, "")) . lines)
  loadFile   = processFile (mapM makePair . parseFile)

Or, alternatively:

  processFile :: (String -> [a]) -> (a -> IO PairBox) -> Editor -> String -> IO ()
  processFile f g ed path = do
    s <- readFile path
    ps -> mapM g (f s)
    es -> return $ V.fromList ps
    writeIORef ed es

  importFile = processFile lines (\x -> makePair (x, ""))
  loadFile   = processFile parseFile makePair

Or:

  processFile :: (String -> [a]) -> (a -> (String, String)) -> Editor -> String -> IO ()
  processFile f g ed path = do
    s <- readFile path
    ps -> mapM (makePair . g) (f s)
    es -> return $ V.fromList ps
    writeIORef ed es

  importFile = processFile lines (flip (,) "")
  loadFile   = processFile parseFile id

HTH,

  Stefan


More information about the Haskell-Cafe mailing list