QuadraticImportOneDataHaskell.hs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. {-# LANGUAGE LambdaCase #-}
  2. -- | Create a sequence of files each of which imports all previous ones
  3. -- and defines one data type and an alias for its only constructor.
  4. --
  5. -- @
  6. -- module FileNNN where
  7. --
  8. -- import qualified File000
  9. -- ...
  10. -- import qualified File(NNN-1)
  11. --
  12. -- data D = C
  13. --
  14. -- test :: D
  15. -- test = C
  16. -- @
  17. import Control.Monad (forM_)
  18. import System.Directory (createDirectoryIfMissing)
  19. import System.Environment (getArgs, getProgName)
  20. import System.FilePath ((</>), (<.>))
  21. import Text.Read (readMaybe)
  22. filePrefix = "File"
  23. mainName = "Main"
  24. main :: IO ()
  25. main = do
  26. getArgs >>= \case
  27. [dir, s] | Just n <- readMaybe s -> run dir n
  28. _ -> usage
  29. usage :: IO ()
  30. usage = do
  31. me <- getProgName
  32. putStr $ unlines
  33. [ unwords [ "usage:", me, "DIRECTORY", "NUM" ]
  34. , "Creates in directory DIRECTORY NUM files named " ++ filePrefix ++ "XXX.hs,"
  35. , "each importing all previous ones, plus a file named " ++ mainName ++ ".hs,"
  36. , "importing all the other files."
  37. ]
  38. run
  39. :: FilePath -- ^ Directory in which to create the files.
  40. -> Int -- ^ Number of files to create.
  41. -> IO ()
  42. run dir n = do
  43. createDirectoryIfMissing True dir
  44. -- Create files
  45. forM_ [0..n-1] $ \ i -> do
  46. let fileName = (filePrefix ++ print0d w i) <.> "hs"
  47. writeFile (dir </> fileName) $ createContent n i
  48. -- Create main file
  49. writeFile (dir </> "Main" <.> "hs") $ createMainContent n
  50. where
  51. w = length $ show n
  52. -- | Created content of main file, importing the others.
  53. createMainContent
  54. :: Int -- ^ Number of files we create.
  55. -> String -- ^ Content.
  56. createMainContent n = unlines $ concat
  57. [ map (\ j -> "import qualified " ++ filePrefix ++ print0d w j) [0..n-1]
  58. , [ ""
  59. , "main :: IO ()"
  60. , "main = return ()"
  61. ]
  62. ]
  63. where
  64. w = length $ show n
  65. -- | Create list of strings containing:
  66. -- @
  67. -- module FileNNN where
  68. --
  69. -- import qualified File000
  70. -- ...
  71. -- import qualified File(NNN-1)
  72. --
  73. -- data D = C
  74. --
  75. -- test :: D
  76. -- test = C
  77. -- @
  78. createContent
  79. :: Int -- ^ Number of files we create.
  80. -> Int -- ^ Number of the file we create here.
  81. -> String -- ^ Content.
  82. createContent n i = unlines $ concat
  83. [ [ unwords [ "module" , filePrefix ++ print0d w i, "where" ]
  84. , ""
  85. ]
  86. , map (\ j -> "import qualified " ++ filePrefix ++ print0d w j) [0..i-1]
  87. , [ ""
  88. , "data D = C"
  89. , ""
  90. , "test :: D"
  91. , "test = C"
  92. ]
  93. ]
  94. where
  95. w = length $ show n
  96. -- | Equivalent to @sprintf("%0<width>d", num)@
  97. print0d
  98. :: Int -- ^ Width.
  99. -> Int -- ^ Print this integer.
  100. -> String -- ^ Padded from the left with 0s.
  101. print0d w i = pad ++ s
  102. where
  103. s = show i
  104. pad = replicate (w - length s) '0'