我的应用程序需要在运行时打开多个资源。我通过openFile在应用程序开始时映射一次来实现这一点。
let filePaths = ["/dev/ttyUSB0", "/dev/ttyUSB1", "/dev/ttyUSB2"]
fileHandles <- mapM (`openFile` ReadWriteMode) filePaths
Run Code Online (Sandbox Code Playgroud)
此代码不安全,因为它可能适用于前 2 个文件路径,但在打开第三个文件路径时会引发异常。在这种情况下,我需要关闭已经打开的前 2 个文件路径,这样我就可以退出该函数而不会泄漏资源。我查看了其中的函数和模式,Control.Exception但没有发现任何对这种情况有帮助的内容。我还没有看过ResourceT。在这种情况下它有帮助吗?
我想我正在寻找与此类似的函数签名:
safeMapM:: [a] -> (a -> IO b) -> (b -> IO()) -> [b]
Run Code Online (Sandbox Code Playgroud)
(b -> IO())发生异常时调用的清理函数在哪里。
我能想到的解决方案可能不好:
Maybe. 可以捕获异常并导致Nothing. 在mapM总能完成,我可以事后检查没什么/异常,并通过他们,然后关闭所有成功打开的文件句柄Just Handle。以下代码示例的执行时间大约为 2 秒。然而,当第 14 行中的刘海图案被移除时,需要 60 秒。谁能解释一下发生了什么事吗?
我使用的是严格的 MVar,因此无论放入 MVar 中的是什么,都应该完全评估为正常形式。我不希望 Bang 模式在插入 MVar 之前产生任何明显的效果。
{-# LANGUAGE BangPatterns #-}
import Control.Concurrent.MVar.Strict
import qualified Data.Text as T
import Data.Text.Encoding
main :: IO ()
main = do
mvar <- newMVar T.empty
let bsArr = map (\i -> encodeUtf8 $ T.pack $ "some strange string " ++ show i) [0 .. 30000 :: Int]
mvarWriter =
\lbs ->
let !decoded = decodeUtf8 lbs
in modifyMVar_ mvar (\oldText -> return $ oldText <> decoded) …Run Code Online (Sandbox Code Playgroud) 我有多个对象,每个对象都与一个字符串关联。是否有某种模式允许以类型安全的方式获取所有字符串的列表?
data MyObject = Foo | Bar
getObjectString :: MyObject -> String
getObjectString Foo = "Foo"
getObjectString Bar = "Bar"
-- Bad because not type safe and String duplication
listOfAllObjectStrings :: [String]
listOfAllObjectStrings = ["Foo", "Bar"]
Run Code Online (Sandbox Code Playgroud)
不同的解决方案仍然不是类型安全的,但减少了字符串重复。
data MyObject = Foo | Bar
getObjectString :: MyObject -> String
getObjectString Foo = listOfAllObjectString !! 0
getObjectString Bar = listOfAllObjectString !! 1
listOfAllObjectStrings :: [String]
listOfAllObjectStrings = ["Foo", "Bar"]
Run Code Online (Sandbox Code Playgroud)