ANN: LocallyLazyRead-0.1 Repository: http://www.patch-tag.com/r/exit/LocallyLazyRead/home (no hackage package since anonymous uploads are not allowed there) The package comprises just one function which applies a lazy parser to a resource that may otherwise be accessed via strict IO:
import Control.LocallyLazyRead
Assume a (lazy) parser:
parse :: Read a => String -> IO (a,String) parse = return . head . reads
Turn this into a "get"-like function which reads the characters strictly but computes the parse result lazily:
foo :: Handle -> IO (String,Char,(Int,Int),Char) foo h = do s <- llread (hGetChar h) parse c1 <- hGetChar h ii <- llread (hGetChar h) parse c2 <- hGetChar h return (s,c1,ii,c2)
where llread is of type IO t -> ([t] -> IO (a,[t])) -> IO a The parser must satisfy the following semantic constraint: For all finite p, arbitrary q, arbitrary a with the right type: (parse (p++q)) computes the value (a,q) in a given IO state if and only if (parse p) computes the value (a,[]) in the same IO state This entails zero lookahead into the unparsed rest, and also a rest which truely depends on the input - parse x = return (x,[]) is forbidden. Violations are detected at runtime:
-- throws a LookaheadAttempt exception: bar :: Handle -> IO Bool bar h = llread (hGetChar h) (\(y:ys)-> return (isSpace y,y:ys))
-- throws a Lookahead exception: barbar :: Handle -> IO Int barbar h = llread (hGetChar h) parse
--- e(x(i(t))) <e.ex.exi.exit@gmail.com> Key fingerprint = A915 1EA1 4D0E 759A B925 0076 A409 2713 E490 3776
participants (1)
-
e.ex.exi.exit@googlemail.com