patternpythonModerate
Script for copying files to the appropriate directory
Viewed 0 times
scriptdirectorytheappropriatefilescopyingfor
Problem
In the book Real World Haskell, the author writes in the first line of every file that uses, for example the following:
I wanted to create a script which reads the first line and copies the files to the appropriate directory. In the above example we should copy the file to the directory ch05. I wanted to write this in Haskell in order to use it for "real world" applications.
But before starting writing to Haskell I wrote it in Python:
And then I tried to write the same code in Haskell:
Haskell code should be more elegant and more compact but it is not. Can you give me suggestions on making the above program more Haskellish?
file: ch05/PrettyJSON. The chapter slash and the name of a module.I wanted to create a script which reads the first line and copies the files to the appropriate directory. In the above example we should copy the file to the directory ch05. I wanted to write this in Haskell in order to use it for "real world" applications.
But before starting writing to Haskell I wrote it in Python:
import os
import shutil
current_dir = os.getcwd()
current_files=os.listdir(current_dir)
haskell_files=filter(lambda x:x.find(".hs")!=-1,current_files)
for x in haskell_files:
with open(x,"r") as f:
header=f.readline()
try:
chIndex=header.index("ch")
except ValueError as e:
continue
number=header[chIndex:chIndex+4]
try:
os.mkdir(number)
shutil.copy2(x,number)
except OSError as e:
shutil.copy2(x,number)And then I tried to write the same code in Haskell:
f x = dropWhile (\x-> x/='c') x
g x = takeWhile (\x-> x=='c' || x=='h' || isDigit x) x
z= do
y<-getCurrentDirectory
e<-getDirectoryContents y
let b=findhs e
mapM w b
findhs filepaths = filter (isSuffixOf ".hs") filepaths
w filename= do
y<-readFile filename
let a=(g.f) y
if "ch" `isPrefixOf` a
then do
createDirectoryIfMissing False a
g<-getCurrentDirectory
writeFile (g ++"/"++ a ++ "/" ++ filename) y
else
return ()
main=zHaskell code should be more elegant and more compact but it is not. Can you give me suggestions on making the above program more Haskellish?
Solution
Notes:
Resulting in:
- don't use single letter variable names for top level bindings
- leave spaces around syntax like
=and
- use meaningful variable names for system values (such as file contents)
- inline single uses of tiny functions, such as your findhs e
- give your core algorithm, w
, a meaningful name
- don't use long names for local parameters like filepaths
.fsis fine.
- use pointfree style for arguments in the final position
- use when
instead ofif .. then ... else return ()
- use the filepath library for nice file path construction
- your only use of f
andgis to compose them. so do that and name the result.
- use section syntax for lambdas as function arguments to HOFs
- indent consistently
- use mapM_` when the result you don't care about.
Resulting in:
import Data.Char
import Data.List
import Control.Monad
import System.Directory
import System.FilePath
clean = takeWhile (\x -> x == 'c' || x == 'h' || isDigit x)
. dropWhile (/='c')
process path = do
y a path) y
main = do
y <- getCurrentDirectory
e <- getDirectoryContents y
mapM_ process $ filter (isSuffixOf ".hs") eCode Snippets
import Data.Char
import Data.List
import Control.Monad
import System.Directory
import System.FilePath
clean = takeWhile (\x -> x == 'c' || x == 'h' || isDigit x)
. dropWhile (/='c')
process path = do
y <- readFile path
let a = clean y
when ("ch" `isPrefixOf` a) $ do
createDirectoryIfMissing False a
g <- getCurrentDirectory
writeFile (g </> a </> path) y
main = do
y <- getCurrentDirectory
e <- getDirectoryContents y
mapM_ process $ filter (isSuffixOf ".hs") eContext
StackExchange Code Review Q#16038, answer score: 17
Revisions (0)
No revisions yet.