Haskell - хотите глобальную переменную из файла, который не изменяется
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]
У меня есть эта функция, которая создает карту для поиска анаграмм из файла словаря, который не изменяется. Я хочу иметь карту в качестве глобальной переменной, так как она должна использоваться другими функциями. В настоящее время функции используют unsafePerformIO в buildAnagrams, но я знаю, что это не рекомендуется. Вся программа также очень медленная, поскольку она строит карту несколько раз. Должен быть лучший способ сделать это?
1 ответ
Если вы хотите сохранить данные анаграммы во внешнем файле, вам нужно IO, чтобы прочитать их. Итак, у вас есть несколько вариантов:
- передача данных анаграммы в качестве дополнительного аргумента для всех ваших функций
- передать те же данные, используя неявный аргумент
- обернуть все в
Reader
монада (или добавитьReaderT
трансформатор) - использование
unsafePerformIO
с обычными оговорками
Около unsafePerformIO
: если вы абсолютно уверены, что прочитанный вами файл не изменится, это один из его "безопасных" вариантов использования. Хотя это и не рекомендуется, либо элегантно, оно может решить эту проблему. Чтобы избежать повторного чтения данных, вы должны использовать
{-# NOINLINE allAnagrams #-}
allAnagrams :: Anagrams
allAnagrams = unsafePermformIO buildAnagrams
так что внешний файл будет прочитан ровно один раз.
Другой вариант - включить внешний файл в исходный код на Haskell. Это можно сделать несколькими способами, в том числе
- простое метапрограммирование: вы пишете программу, которая берет ваш внешний файл и конвертирует его в файл.hs, который объявляет большой вектор строки
- Шаблон Haskell: тот же эффект, что и метапрограммирование, но немного более элегантный