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]
Run Code Online (Sandbox Code Playgroud)
我有这个函数,它构建一个映射来从字典文件中查找anagrams,该文件不会改变.我希望将地图作为全局变量,因为它需要被其他函数使用.目前函数在buildAnagrams上使用unsafePerformIO,但我知道不建议这样做.整个程序也很慢,因为它多次构建地图.必须有更好的方法来做到这一点?
以下是示例程序的来源:
当我从ghci运行它时,printJob和printJob2运行正常并将十行写入文本文件.
但是当使用-threaded标志编译时,程序只写一行.
我在ArchLinux上有ghc 7.0.3
这是编译命令:
ghc -threaded -Wall -O2 -rtsopts -with-rtsopts=-N -o testmvar testmvar.hs
Run Code Online (Sandbox Code Playgroud)
我做错了什么?为什么它不能在线程模式下工作?
import Control.Concurrent.MVar
import Control.Concurrent (forkIO)
import Control.Exception (bracket)
import Control.Monad (forM_)
import System.IO.Unsafe (unsafePerformIO)
import System.IO (hPutStrLn, stderr)
{-# NOINLINE p #-}
p :: MVar Int
p = unsafePerformIO $ newMVar (1::Int)
{-# NOINLINE printJob #-}
printJob x = bracket (takeMVar p) (putMVar p . (+ 1))
(\a -> do
appendFile "mvarlog.txt" $ "Input: " ++ x ++ "; Counter: " ++ show a …Run Code Online (Sandbox Code Playgroud) 在haskell中,我需要一个全局变量,所以我选择使用IORef插槽,这是我的计划:
memo :: IORef Int
memo = unsafePerformIO $ newRefInt 9999
evaluate ARGs s = do
v <- Right $ unsafePerformIO $ readIORef memo
val <- Right $ VInt v
return $ (val, s)
evaluate (Call funcID exp) s = do
...
Right $ writeIORef memo 100
...
Run Code Online (Sandbox Code Playgroud)
我的计划是当执行者评估"呼叫"节点时,它会将参数保存到插槽中.然后,当评估"ARGs"节点时,将读取该备忘录槽.
但无论我做什么,我只能读取9999但不能在该槽中写入新值.
甚至我试过:
memo :: IORef Int
memo = unsafePerformIO $ newRefInt 9999
evaluate ARGs s = do
Right $ writeIORef memo 100
v <- Right $ unsafePerformIO $ readIORef memo
val …Run Code Online (Sandbox Code Playgroud) 我有
sample :: MVar a -> IO [a]
sample v = do
a <- takeMVar v
pure (a:unsafePerformIO (sample v))
Run Code Online (Sandbox Code Playgroud)
这似乎是unsafePerformIO对我的合法使用.但我很想知道如何避免它!是否有这种用途的模式?