2010-08-11 8 views
1

나는 하스켈 에서 프로그램을 쓰고 읽기는 여기가이상한 행동 파일

module Main 
where 
import IO 
import Maybe 
import Control.Monad.Reader 
--il mio environment consiste in una lista di tuple/coppie chiave-valore 
data Environment = Env {variables::[(String,String)]}deriving (Show) 

fromEnvToPair :: Environment-> [(String,String)] 
fromEnvToPair (Env e)= e 

estrai' x d 
|length x==0=[] 
|otherwise=estrai x d 
estrai (x:xs) d 
| (x:xs)=="" =[] 
| x== d=[] 
| otherwise = x:(estrai xs d) 
--estrae da una stringa tutti i caratteri saino a d 
conta' x d n 
| length x==0 = 0 
|otherwise = conta x d n 
conta (x:xs) d n 
| x== d=n 
| otherwise = (conta xs d (n+1)) 
primo (a,b,c)=a 
secondo (a,b,c)=b 
terzo (a,b,c)=c 

estraifrom x d n 
|n>=(length x) =[] 
| x!!n==d = [] 
|otherwise = x!!n:(estraifrom x d (n+1)) 

readerContent :: Reader Environment Environment 
readerContent =do 
content <- ask 
return (content) 

-- resolve a template into a string 
resolve :: [Char]-> Reader Environment (String) 
resolve key= do 
varValue <- asks (lookupVar key) 
return $ maybe "" id varValue 

maketuple x =(k,v,l) where 
k= (estrai' x ':')--usare estrai' 

v=estraifrom x ';' (conta' x ':' 1) 
l= (length k)+(length v)+2 --è l'offset dovuto al; e al : 
makecontext x 
| length x==0 = [] 
| (elem ':' x)&&(elem ';' x)==False = [] 
|otherwise= (k,v):makecontext (drop l x) where 
    t= maketuple x 
    k= primo t 
    v= secondo t 
    l= terzo t 



doRead filename = do 
    bracket(openFile filename ReadMode) hClose(\h -> do 
     contents <- hGetContents h 
     return contents 
     let cont=makecontext contents 
     putStrLn (take 100 contents) 
     return (contents)) 
--   putStrLn (snd (cont!!1))) 
--   putStrLn (take 100 contents)) 


-- estrae i caratteri di una stringa dall'inizio fino al carattere di controllo 
-- aggiungere parametri to the environment 

-- estrae i caratteri di una stringa dall'inizio fino al carattere di controllo 
-- aggiungere parametri to the environment 



-- lookup a variable from the environment 
lookupVar :: [Char] -> Environment -> Maybe String 
lookupVar name env = lookup name (variables env) 
lookup' x t=[v| (k,v)<-t,k==x] 





fromJust' :: Maybe a -> a 
fromJust' (Just x) = x 
fromJust' Nothing = error "fromJust: Nothing" 

main = do 

file<- doRead "context.txt"-- leggo il contesto 
let env= Env(makecontext file) -- lo converto in Environment 
let c1= fromEnvToPair(runReader readerContent env) 
putStrLn(fromJust'(lookupVar "user" env)) 
--putStrLn ((lookup' "user" (fromEnvToPair env))!!0)-- read the environment 
--putStrLn ("user"++ (fst (c1!!1))) 
putStrLn ("finito") 
--putStrLn("contesto" ++ (snd(context!!1))) 

은 내가 내용을 포맷하기 및 환경에 퍼 팅 파일을 읽고 싶은, 잘가 읽을 코드를입니다 파일을 읽고 doRead가있는 경우에만 다른 모든 작업을 수행합니다. putStrLn (100 개의 내용 가져 오기) 그렇지 않으면 나는 anithing을 가져갈 수 없습니다. 왜 누군가는 그 이유를 알고 있습니까? 이유를 모르는 경우 그 줄을 남기고 싶지 않습니다. 미리 감사드립니다.

답변

0

하스켈 파서 라이브러리 중 하나를 사용하면 이런 종류의 작업을 훨씬 덜 고통스럽고 오류가 발생하기 쉽습니다. 여기 Attoparsec이 작업을 수행하는 방법의 예는 다음과 같습니다

module Main where 

import Control.Applicative 
import qualified Data.Map as M 
import Data.Attoparsec (maybeResult) 
import qualified Data.Attoparsec.Char8 as A 
import qualified Data.ByteString.Char8 as B 

type Environment = M.Map String String 

spaces = A.many $ A.char ' ' 

upTo delimiter = B.unpack <$> A.takeWhile (A.notInClass $ delimiter : " ") 
          <* (spaces >> A.char delimiter >> spaces) 

entry = (,) <$> upTo ':' <*> upTo ';' 

environment :: A.Parser Environment 
environment = M.fromList <$> A.sepBy entry A.endOfLine 

parseEnvironment :: B.ByteString -> Maybe Environment 
parseEnvironment = maybeResult . flip A.feed B.empty . A.parse environment 

우리가 파일 context.txt이있는 경우 다음과 같이

user: somebody; 
home: somewhere; 
x: 1; 
y: 2; 
z: 3; 

우리는 파서를 테스트 할 수 있습니다

*Main> Just env <- parseEnvironment <$> B.readFile "context.txt" 
*Main> print $ M.lookup "user" env 
Just "somebody" 
*Main> print env 
fromList [("home","somewhere"),("user","somebody"),("x","1"),("y","2"),("z","3")] 

참고하는 I camcann이 이전 Reader 모나드 질문에 대한 의견에서 제안했듯이, Map을 사용하여 환경을 나타냅니다.

0

게으름이라고 생각합니다. 해당 내용이 실제로 읽히기 전에 파일 핸들이 닫힙니다. 핸들을 닫기 전에 일부 내용을 가져 와서 인쇄하면 핸들을 반환하거나 닫기 전에 내용을로드해야합니다.

System.IO.StrictreadFile 기능을 사용하는 것이 좋습니다. 그것은 엄격하게 (게으른) 내용을로드하고, 파일 핸들을 사용하는 일부 통증을 저장합니다. doRead에 대한 호출을 readFile로 바꾸기 만하면됩니다. 동일한 형식 시그니처가 있기 때문입니다.