type Anagrams = Map String [String]
buildAnagrams :: IO Anagrams
buildAnagrams = do
list <- readCSV "mydict.csv"
return $ foldr f Map.empty list
where
f :: String -> Anagrams -> Anagrams
f s = Map.insertWith (++) (sort s) [s]
I have this function that build a map to lookup anagrams from a dictionary file which does not change. I want to have the map as a global variable as it needs to be used by other functions. At the moment the functions are using unsafePerformIO on buildAnagrams but I am aware that is is not recommended. The whole program is also very slow as it is building the map multiple times. There must be a better way to do this?
If you want to keep the anagram data in an external file, you need IO to read it. So, you have a few options:
Reader
monad (or add a ReaderT
transformer)unsafePerformIO
, with the usual caveatsAbout unsafePerformIO
: if you're absolutely sure that the file you read is not going to change, this is one of its "safe" use cases. While not really recommended, or elegant, it could solve this problem. To avoid re-reading the data multiple times, you should use
{-# NOINLINE allAnagrams #-}
allAnagrams :: Anagrams
allAnagrams = unsafePermformIO buildAnagrams
so that the external file will be read exactly once.
Another option would be to include your external file in your Haskell source. This can be done in a few ways, including