Reputation: 1
my program is supposed to go through all of the files in a given directory, and append a counter to the content of each file with the extension ".vm". however, it has an error "couldn't mach type [] with IO" in the append. if anyone can help i'll be geatfull
my code:
import System.IO
import qualified Data.ByteString.Lazy.Char8 as B
import Control.Applicative
import Data.List
import System.Directory
import System.FilePath
main = do
files <- getDirectoryContents "c:/program file"
let filtered = filter ( vmExtention ) files
[ appendFile x y| x<-filtered, y <- [0..] ]
print filtered
print files
vmExtention :: FilePath-> Bool
vmExtention s =
if ( takeExtension s )== ".vm" then True else False
Upvotes: 0
Views: 277
Reputation: 105886
[ appendFile x y| x<-filtered, y <- [0..] ]
That's a stray list comprehension of type [IO ()]
if appendFile x y
was valid (it's not). You have to use sequence
or similar:
sequence [ appendFile x y| x<-filtered, y <- [0..] ]
However, this won't work, since y
must be a String
, and [0..]
is an infinite list, so you would end up with
appendFile x 0
appendFile x 1
appendFile x 2
appendFile x 3
...
You want something along
sequence [appendFile file (show counter) | (file, counter) <- zip filtered [0..]]
Upvotes: 3
Reputation: 34810
import System.IO
import qualified Data.ByteString.Lazy.Char8 as B
import Control.Applicative
import Data.List
import System.Directory
import System.FilePath
import Debug.Trace
debug = flip trace
main = do
let path = "/tmp/test"
files <- getDirectoryContents path
let filtered = filter ( vmExtention ) files
let filteredWithIndex = zip filtered [0..]
sequence_ [ appendFile' (path </> fp) (show i) | (fp,i) <- filteredWithIndex ]
appendFile' fp s =
-- note that the path was relative but is now fixed
appendFile fp s `debug` ("filepath: " ++ fp)
vmExtention :: FilePath-> Bool
vmExtention s =
takeExtension s == ".vm"
Upvotes: 0
Reputation: 416
In your code, files
is a list of IO actions ([IO ()]
), so to execute the IO actions in the list, you can simply call sequence files
. However, you also need to correct the list comprehension - as it stands, it will attempt to add all integers in the range [0..]
to the end of the first file (the ranges in the list comprehension are nested from left to right, i.e,. given x<-A, y<-B
, for each x, we take a y from B until B is exhausted, before taking the next x). A better list comprehension would be
let files = [appendFile (path </> x) (show y) | zip filtered [0..] ]
Note you also need to add the path to the beginning of the filename (I added let path = "c:\program file"
to the beginning of the main function), and you need to show
the integer to turn it into a string for appendFile.
Upvotes: 0