簡體   English   中英

在 Polysemy 中將一元值轉換為 IO

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM