[英]Converting a monadic value to an IO in Polysemy
我正在嘗試在polysemy
中使用webdriver
和 polysemy 構建一個自動化功能測試套件。 我已經定義了適當的效果並將它們解釋為 webdriver WD monad,但現在我被卡住了。
我有一個Member BrowserMaster r => Sem r ()
類型的值,其中BrowserMaster
是我的自定義功能。
這是口譯員:
runBrowserMaster :: Members [Embed WD.WD, Embed IO] r => Sem (BrowserMaster ': r) a -> Sem r a
runBrowserMaster = interpret $ \case
ClickElement bmSelector ->
let action = (WD.findElem (bmSelectoToSelector bmSelector) >>= WD.click :: WD.WD ())
in embed action
{- ... -}
現在我想知道如何將Embed WD.WD
效果轉換為Embed IO
,這樣我就只有一個。
我試圖制作一個口譯員:
runWebDriver :: Member (Embed IO) r => Sem (Embed WD.WD ': r) a -> Sem r a
runWebDriver = interpret $
\a -> embed $ runSession chromeConfig . finallyClose $ do
setImplicitWait 60000
setWindowSize (1024, 768)
unEmbed a
(這里runSession chromeConfig. finallyClose
是一個WD a -> IO a
)
它確實有效,但它似乎為每個命令啟動了一個新的瀏覽器 session,而不是只啟動一次,在內部完成所有操作並關閉。
我有一種直覺,它必須與資源獲取和釋放有關,但我無法理解這一點,無法將它們放在一起。
請記住,每次執行BrowserMaster
效果的操作時,都會執行每個解釋器。 所以每次它運行runWebDriver
解釋器,這就解釋了為什么它創建、運行和關閉 session。
我認為您想要做的是創建/刪除 session 一次,並在此 session 中執行您的整個代碼。 此外,由於WD
已經是IO
的包裝,我認為沒有必要同時嵌入這兩種效果。
我不熟悉您的代碼或webdriver
庫,但我認為這將類似於:
main :: IO ()
main = runSession chromeConfig . finallyClose $ do
setImplicitWait 60000
setWindowSize (1024, 768)
runM . runBrowserMaster $ myBusinessCode
runBrowserMaster :: Member (Embed WD.WD) r => Sem (BrowserMaster ': r) a -> Sem r a
runBrowserMaster = interpret $ \case
ClickElement bmSelector ->
let action = (WD.findElem (bmSelectoToSelector bmSelector) >>= WD.click :: WD.WD ())
in embed action
{- ... -}
注意:如果您需要在解釋器中運行一些IO
代碼,請使用liftIO
使其成為WD
操作,例如liftIO $ putStrLn "Hello world"
。
PS:我建議將runBrowserMaster
解釋器重命名為browserMasterToWD
之類的名稱,因為它可以更好地代表它的作用:根據WD
動作解釋BrowserMaster
效果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.