[Haskell-cafe] Is StateT what I need?

Andre Nathan andre at digirati.com.br
Mon Dec 17 14:33:20 EST 2007


Hello (Newbie question ahead :) 

I'm trying to write a program which will build a tree (here represented
as a Map) of unix processes. The tree should be built by reading the
process information stored in /proc/PID/status. There is also another
Map which will be used for faster insertions on the process tree, which
I'd like to handle as my program state. So far I have the functions to
get a list of entries from /proc, filter the ones that represent
processes and get the information from their status file.

Now I need an "insertProc" function, which should get the information
for a given process ID, update the state and return that information.
This is where I think I need StateT, but I couldn't find out how to use
it (never used StateT before...).

This is what I have so far:

> type Pid = FilePath
> type Uid = String
>
> type PsData     = Map String Uid
> type PsChildren = Map Pid PsInfo
>
> data PsInfo = PsInfo PsData PsChildren
> type PsMap  = Map Pid PsInfo
> type PsTree = Map Pid PsInfo
>
> parent :: PsData -> Pid
> parent psData = fromJust $ Map.lookup "PPid" psData
>
> getProcInfo :: PsData -> String -> IO PsData
> getProcInfo psData line = do
>   case matchRegex (mkRegex "^([a-z]+):[[:space:]]+(.*)$") line of
>     Nothing           -> return (psData)
>     Just [key, value] -> return (Map.insert key value psData)
>
> procInfo :: Pid -> IO PsInfo
> procInfo pid = do
>   procData <- readFile $ "/proc/" ++ pid ++ "/status"
>   psData <- foldM getProcInfo Map.empty (lines procData)
>   let [rUid, eUid, _] = words $ fromJust (Map.lookup "Uid" psData)
>   let [rGid, eGid, _] = words $ fromJust (Map.lookup "Gid" psData)
>   let uids = Map.fromList [("RUid", rUid), ("EUid", eUid),
>                            ("RGid", rGid), ("EGid", eGid)]
>   let psData' = Map.union psData uids
>   return (PsInfo psData' Map.empty)

I tried this for insertProc, but it obviously doesn't work... what would
be the correct way to do this?

> insertProc :: Pid -> StateT PsMap IO PsInfo
> insertProc pid = do
>   proc <- procInfo pid -- XXX this is obviously wrong...
>   psMap <- get
>   put (Map.insert pid proc psMap)
>   return (proc)

A second question: is it possible to make getProcInfo's type to be
PsData -> String -> PsData and use some operation similar to lift so
that it can be used with foldM, instead of making its return type to be
IO PsData explicitely?


Thanks in advance,
Andre



More information about the Haskell-Cafe mailing list