我在Haskell写一个程序 这是代码
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 :(得分:0)
我认为问题是懒惰。在实际读取内容之前关闭文件句柄。通过在关闭手柄之前获取并打印一些内容,您可以在返回/关闭手柄之前强制它加载它。
我建议使用readFile
中的System.IO.Strict
功能。它严格加载内容(非延迟),并且还可以节省使用文件句柄的一些麻烦。您只需使用readFile替换对doRead的调用,因为它具有相同的类型签名。
答案 1 :(得分:0)
使用其中一个Haskell解析器库可以使这种事情变得更加痛苦和容易出错。以下是使用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")]
请注意,我使用Map
来表示环境,正如camcann在您之前的Reader
monad问题的评论中所建议的那样。