I have been given a list xs
and a function f
, and I want to know stuff like how many x <- xs
satisfy (f x) `elem` xs
or which ones do, etc. However, the problem is that the list xs
is available only as an external file.
import Data.Char
import System.IO.Strict
import qualified Data.Set as Set
vowel x = elem x "aeiou"
toPigLatin :: String -> String
toPigLatin word
| vowel (head word) = word ++ "ay"
| not $ null [x | x <- word, vowel x] = let (v, c) = span (not.vowel) word in c ++ v ++ "ay"
| otherwise = word
wordList = lines <$> System.IO.Strict.readFile "toyWordSet"
wordSet = Set.fromList <$> wordList
good :: String -> IO Bool
good word = (Set.member (toPigLatin word)) <$> wordSet
mapMBool :: (a -> IO b) -> [a] -> IO [b]
mapMBool f l = do
case l of
[] -> return []
(x:xs) -> do
b1 <- f x
bs <- mapMBool f xs
return (b1:bs)
Ultimately, I want to compute wordList >>= mapMBool good
, which is a value of type IO [Bool]
which have True
at the positions where the desired property is satisfied.
Now, I have three main concerns:
- When I run my code with a
toyWordSet
, it runs fine but I ultimately intend to replace it with/usr/share/dict/words
, on which my PC freezes. How do I make my program more efficient? - Writing a function like
mapMBool
is not the most elegant idea ever. How can I do this more elegantly? - For some reason, I get some strange exceptions, when I try to use the lazy
readFile
instead of the strict version. What is happening? Why must I use strictness?
Other general comments on the coding style or practice is also welcome.
mapMBool
is justmapM
. \$\endgroup\$ – Gurkenglas Jan 8 '18 at 19:14