2016-12-05 46 views
1

閱讀Yesod書籍後,我想到了使用類型安全URL而不是原始字符串的想法。我只是嘗試一些簡單的獲取請求,而不是使用完整的yesod庫,但似乎很容易定義自定義URL數據類型派生節目,或使用其他一些現有的最小URL庫。在Haskell中使用Network.URL庫

我發現這對Hoogle: https://hackage.haskell.org/package/url-2.1.3/docs/Network-URL.html

好像它會做我想要的那種驗證,因此像一個錯誤:

myothervar = "kittens" -- oh no, I defined this for something else 
parseRequest myothervar -- and called it from parseRequest! 

將被編譯器捕獲,而

myurl = "http://example.com" 
parseRequest myurl 

...會成功,很好。

ghci λ> import Network.URL 
ghci λ> myurl = importURL "http://example.com" 

文檔建議給我,我需要使用importURL

ghci λ> :t myurl 
myurl :: Maybe URL 

太好了,我知道如何去Maybe,我用Just

ghci λ> exportURL $ Just myurl 

<interactive>:47:13: error: 
    • Couldn't match expected type ‘URL’ 
        with actual type ‘Maybe (Maybe URL)’ 
    • In the second argument of ‘($)’, namely ‘Just myurl’ 
     In the expression: exportURL $ Just myurl 
     In an equation for ‘it’: it = exportURL $ Just myurl 

ghci λ> Just (Just (URL {url_type = Absolute (Host {protocol = HTTP False, host = "example.com", port = Nothing}), url_path = "", url_params = []})) 

好的,什麼?這並沒有刪除我的Just,它只是添加了另一個Just。我如何檢索parseRequest將作爲參數的字符串?

它看起來像我肯定需要取消也許是由出口返回字符串莫名其妙:

ghci λ> import Network.HTTP.Conduit 
ghci λ> parseRequest $ myurl 

<interactive>:84:16: error: 
    • Couldn't match type ‘Maybe URL’ with ‘[Char]’ 
     Expected type: String 
     Actual type: Maybe URL 
+1

Err,'Just'不是「de-maybe」,它是'Maybe'類型的兩個構造函數之一。事實上,你*不可能*也許一般來說,因爲如果值是'Nothing'呢? 「值內不會有」URL「。如果你確定它的價值真的是「Just」,那麼你可以使用'fromJust',但是要謹慎使用它!它只會在運行時崩潰你的程序,如果該值不是「Just」,則拋出使用'Maybe'的整個類型安全點。 –

+1

在「de-maybe」問題上,您可能會混合使用'Just'作爲函數來構建一個'Maybe'值(例如,在您感到驚訝的類型不匹配中)與其用於模式匹配(例如,在等號的左側)。有關如何處理'Maybe'值的建議,[*從包含「Just」*(http://stackoverflow.com/q/3375483/2751851)的Maybe中返回是一個好的開始。 – duplode

回答

2

有幾件事情值得在這裏討論:

OK,什麼?這並沒有刪除我的Just,它只是添加了另一個Just。我如何檢索parseRequest將作爲參數使用的字符串?

記住的東西,有型Maybe URL要麼是NothingJust url其中url :: URL。您不能僅僅「提取」URL的某些部分,因爲Maybe的整個點是您可能根本沒有URL根本就沒有

如何檢索parseRequest將作爲參數使用的字符串?

這是不必要的 - parseRequest正在做同樣的事情importURL - 它只是檢查該網址是否正確形成。唯一的區別是它通過從MonadThrow使用throwM發出錯誤來指示錯誤。此外,如果您想使用http-conduit,則反正您需要使用parseRequest以獲得Request,因此根本沒有必要讓importURL出現。

如果您擔心形成不良的URL,您可以確保將代碼包裝在catch中。

import Network.Connection (TLSSettings (..)) 
import Network.HTTP.Conduit 

main :: IO() 
main = catch (do 
       request <- parseRequest "https://github.com/" 
       let settings = mkManagerSettings (TLSSettingsSimple True False False) Nothing 
       manager <- newManager settings 
       res <- httpLbs request manager 
       print res) 
      (\e -> case e of 
         HttpExceptionRequest{} -> putStrLn "Http request failed" 
         InvalidUrlException{} -> putStrLn "Bad URL")