
Daniel McAllansmith:
The problem is that hGetContents only reads the contents of the file on demand and, without the 'return $!' you don't demand the value until somewhere outside of rechf. By this point the hClose has happened and hGetContents has no access to the file => no lines => no result.
Using 'return $!' is demanding the value of rech r $ lines f immediately so hGetContents accesses the file before the hClose.
hGetContents is implemented using unsafePerformIO so, unless you're very careful, you could get other weird behaviours.
For example, if the value for the key being searched is very long (>8k on my system), it is likely to be truncated. This is because "return $!" only reduces its argument to WHNF. In other words, it only demands enough to work out whether the key is present, which means that hGetContents only gets a chance to return the first block of data retrieved after the key is found, before the file is closed. So, instead of "return $! rech r $ lines f", you really need something like: case (rech r $ lines f) of Just s -> return $! Just $! foldr seq s s Nothing -> return Nothing