
prad
On Sun, 15 Aug 2010 21:11:52 +0200 Ertugrul Soeylemez
wrote: Just remember this: You have an IO computation? You want to refer to its result? Fine, just use '<-'. That's it.
that's what i've been doing the past two days and it works ... except in one case.
for example, i have:
======== flData <- readFile key let (sec:tle:kwd:dsc:url:typ:dat:txt) = lines flData ========
so flData is the computation which reads the contents of a file and i can take that and do a lines on it. no problem.
I have the impression that you have understood the problem, but you have yet to realize that you have. Your 'subs' function needs the contents of a file, so either you pass those contents explicitly or it needs to become an IO computation, so it can read them itself. Anyway, honestly I don't understand what your 'subs' function is about. It seems to interpret stuff after "```", but you can write this a whole lot simpler and probably more correct, although still very fragile: subs :: [String] -> [String] subs [] = [] subs ("```" : code : ts) = gt code : subs ts subs (t:ts) = t : subs ts Why is this fragile? Well, try the following: subs ["```"] Also do yourself and others a favor and write type annotations at least for all top level definitions. Yes, Haskell has type inference, but for important parts of your code you should really write explicit type annotations. Reason: First of all, the types of your functions are the specification of your program. To write a function, the very first thing you should do is to write its type signature. Never start with the function definition. Sometimes you write a valid function, which doesn't match your intended specification. Also given the type signature you can reason much better about whether your code really does what it should do, without even compiling it. Secondly type annotations make your program far more readable. For some really simple one-liner functions they aren't strictly necessary for readability, but personally I write them even for the simplest functions/values. Now what's the type of your function, when it should read a file? Think about it for a while. One very easy way is to give it the contents of the file as a parameter: subs :: String -> [String] -> [String] Another reasonable way is to let the function read the file itself: subs :: FilePath -> [String] -> IO [String] But beware: The way you were going to do it is very bad. It would read the file once for each occurence of "```". Better read the file at the beginning only, at which point you can just as well split this into two functions: subs :: String -> [String] -> [String] subsUsingFile :: FilePath -> [String] -> IO [String] This particular way to make a nonmonadic functions monadic is called lifting, and because it is such a common thing to do, there are loads of combinators to do it, most notably liftM, fmap and (<$>), which are all the same (though liftM can be used in monads only): liftM :: Monad m => (a -> b) -> (m a -> m b) fmap :: Functor f => (a -> b) -> (f a -> f b) (<$>) :: Functor f => (a -> b) -> (f a -> f b) The subsUsingFile function can be implemented in one of the following ways: -- Raw: subsUsingFile fn ts = do content <- readFile fn return (subs content ts) -- Using lifting: subsUsingFile fn ts = liftM (`subs` ts) $ readFile fn subsUsingFile fn ts = fmap (`subs` ts) $ readFile fn subsUsingFile fn ts = (`subs` ts) <$> readFile fn Further note that you are overusing do-notation, even for nonmonadic code. Read section 6 of my tutorial [1] or a HaskellWiki article about this [2]. Whenever you see this pattern: do x <- c return (f x) you should consider using lifting: f <$> c and don't use do-notation if all you want to do is to make an equation: let x = y in ... especially when your code is not monadic. Your use of the do-notation in your 'subs' function works only incidentally, because it is indeed a monadic function, but not in the IO monad, but in the list monad. [1] http://ertes.de/articles/monads.html#section-9 [2] http://www.haskell.org/haskellwiki/Do_notation_considered_harmful Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/