2017-02-02 1 views
0

Ich bin Anfänger, also bitte bitte mit mir.So kombinieren Sie WebDriver und Scotty Monaden

Ich habe einen folgenden Code ein:

{-# LANGUAGE OverloadedStrings #-} 

module Lib where 

import   Control.Monad.IO.Class 
import   Control.Monad.Trans.Class 
import   Data.Monoid    ((<>)) 
import qualified Data.Text     as T 
import qualified Data.Text.Lazy   as TL 
import   Test.WebDriver 
--import   Web.Scotty 
import   Web.Scotty.Trans 

firefoxConfig :: WDConfig 
firefoxConfig = defaultConfig 

startMyBrowser :: WD a -> IO a 
startMyBrowser = runSession firefoxConfig 

stopMyBrowser = closeSession 

someFunc :: WD String 
someFunc = do 
    openPage "http://maslo.cz" 
    captionElem <- findElem (ByCSS "h2") 
    text <- getText captionElem 
    return $ T.unpack text 

helloAction :: ActionT TL.Text WD() 
helloAction = do 
    a <- lift someFunc 
    text $ "got this for you: " <> TL.pack a 

routes :: ScottyT TL.Text WD() 
routes = get "/hello" helloAction 

startServer = startMyBrowser $ do 
    lift $ scottyT 3000 _ routes 
    stopMyBrowser 

Ich bin nicht sicher, selbst wenn diese gefüllte Teile richtig sind - es soll eine Selen-Sitzung (startMyBrowser) starten, einen Web-Server spin up (den scottyT Teil) und nachdem der Webserver gestoppt wurde, sollte er die Selenium-Sitzung beenden (stopMyBrowser).

Nachdem ich mit den Typen herumgespielt habe, bin ich zu dem obigen Code gekommen und es scheint, dass ich nur einen Teil vermisse - das Loch.

Bitte, wenn es funktioniert, versuchen Sie, Ihre Lösung zu erklären und/oder fügen Sie einige Links zu weiteren Materialien hinzu. Ich würde diese verdammten Transformatoren gerne verstehen.

Edit 1: Hier werden die Fehler sind:

• Couldn't match type ‘t0 m0’ with ‘WD’ 
    Expected type: WD() 
     Actual type: t0 m0() 
    • In a stmt of a 'do' block: lift $ scottyT 3000 _ routes 
    In the second argument of ‘($)’, namely 
     ‘do { lift $ scottyT 3000 _ routes; 
      stopMyBrowser }’ 
    In the expression: 
     startMyBrowser 
     $ do { lift $ scottyT 3000 _ routes; 
      stopMyBrowser } 


    • Found hole: 
     _ :: WD wai-3.2.1.1:Network.Wai.Internal.Response 
      -> IO wai-3.2.1.1:Network.Wai.Internal.Response 
    • In the second argument of ‘scottyT’, namely ‘_’ 
    In the second argument of ‘($)’, namely ‘scottyT 3000 _ routes’ 
    In a stmt of a 'do' block: lift $ scottyT 3000 _ routes 
    • Relevant bindings include 
     startServer :: IO() (bound at src/Lib.hs:37:1) 

Antwort

0

Art Kerl ForTheFunctionGod auf reddit answered it, hier ist sie:

Es ist Ihr Problem:

lift $ scottyT 3000 _ routes 

Seit der Rückgabetyp von scottyT ist

MonadIO n => n 

Sie müssen es nicht anheben - es kann in jede Monade passen, die IO-Aktionen ausführen kann. WD ist so ein Monad - Note seine MonadIO Instanz. Sie müssten nur scottyT anheben, wenn der Rückgabetyp ein einfacher IO wäre.

Typenklassen wie MonadIO, MonadState usw. erübrigen sich meist die Notwendigkeit, Berechnungen manuell zu starten. Während Sie eine Funktion auf Typ IO Int abheben müssten, wenn Sie es in StateT s IO Int einbetten möchten, müssten Sie eine Funktion des Typs MonadIO m => m a nicht abheben, weil StateT s IO bereits eine Instanz von MonadIO ist, so dass m instanziiert werden kann .

Wie für das Loch: es hat von

Typ sein
WD Response -> IO Response 

Der einzige Weg, diese Arbeit zu machen, ist runSession oder einem seiner Freunde zu verwenden. Ich weiß nicht, Selen, die gut, aber vermutlich, können Sie Ihre bereits geöffnete Sitzung id wiederverwenden:

runWD :: WDSession -> WD a -> IO a 

startServer = startMyBrowser $ do 
    sessionID <- getSession 
    scottyT 3000 (runWD sessionID) routes 
    stopMyBrowser 

Ich habe nicht versucht, aber die Typen sollen überprüfen. Ich hoffe, es hilft!


Es hat auf jeden Fall :).

Verwandte Themen