# Haskell Quiz/Index and Query/Solution Jethr0

Unfortunately this solution doesn't really address the problem :)

Neither are bit-arrays used nor is this solution saving much space. I just wanted to experiment with the State Monad, and I'm quite happy with what I learned.

Example:

```> let docs = [("Doc1", "The quick brown fox")
,("Doc2", "Jumped over the brown dog")
,("Doc3", "Cut him to the quick")]
> finder docs "brown"
["Doc1","Doc2"]
> finder docs "the"
["Doc2","Doc3"]
```

Solution:

```import qualified Control.Monad.State as State
import qualified Data.Map as Map
import qualified Data.Set as Set

data Rd = Rd {rdN   :: Integer
,rdMap :: Map.Map String Integer
} deriving (Show)

-- process words of a file and return the set of indices
processWords :: [String] -> State.State Rd (Set.Set Integer)
processWords = foldM step (Set.empty) where
step ws x = do mp <- State.gets rdMap
i <- case Map.lookup x mp of
Nothing -> do n <- State.gets rdN
State.modify (\s -> s{rdN=(n+1), rdMap=Map.insert x n (rdMap s)})
return n
Just a  -> return a
return \$ Set.insert i ws

processFile :: (String,String) -> State.State Rd (String, [Integer])
processFile (doc,str) = do indices <- processWords (words str)
return (doc, Set.toList indices)

-- find all documents containing string "str" as a word.
findDocs :: String -> [(String,[Integer])] -> State.State Rd [String]
findDocs str indices = do mp <- State.gets rdMap
case Map.lookup str mp of
Nothing -> return []
Just i  -> return . map fst . filter (\(_,is) -> i `elem` is) \$ indices

runIt f = State.evalState f (Rd {rdN=0, rdMap=Map.empty})
finder ds str = runIt (mapM processFile ds >>= findDocs str)
```