Haskell - 想要从不改变的文件中获取全局变量

时间:2014-12-08 11:33:21

标签: haskell unsafe-perform-io

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]

我有这个函数构建一个映射来从字典文件中查找anagrams,该文件不会改变。我希望将地图作为全局变量,因为它需要被其他函数使用。目前函数在buildAnagrams上使用unsafePerformIO,但我知道不建议这样做。整个程序也很慢,因为它多次构建地图。必须有更好的方法来做到这一点吗?

1 个答案:

答案 0 :(得分:5)

如果要将anagram数据保存在外部文件中,则需要IO才能读取它。所以,你有几个选择:

  • 传递anagram数据作为所有功能的额外参数
  • 使用implicit argument
  • 传递相同的数据
  • 将所有内容包装在Reader monad中(或添加ReaderT变换器)
  • 使用unsafePerformIO
  • unsafePerformIO

关于{-# NOINLINE allAnagrams #-} allAnagrams :: Anagrams allAnagrams = unsafePermformIO buildAnagrams :如果您完全确定您阅读的文件不会改变,那么这是其“安全”用例之一。虽然不是真的推荐或优雅,但它可以解决这个问题。为避免多次重读数据,您应该使用

{{1}}

以便外部文件只读取一次。

另一种选择是将您的外部文件包含在Haskell源中。这可以通过几种方式完成,包括

  • 普通元编程:你编写一个程序,它接收你的外部文件并将其转换为.hs文件,声明一个大的字符串向量
  • usual caveats:与元编程效果相同,但更优雅