我是一名Haskell初學者,目前正在使用wreq來製作一個圍繞api的簡單包裝。如果提供時間,我想發送一個if-modified-since
標題。我按照以下方式這樣做。Haskell/Wreq - 對http請求的複雜類型簽名的建議
getResponse :: (FormatTime t, Exception e) => File -> Maybe t -> IO (Either e (Response L.ByteString))
getResponse file (Just t) =
let formattedTime = (B.pack . formatTime defaultTimeLocale rfc822DateFormat) t
opts = defaults & header "if-modified-since" .~ [formattedTime]
in try $ getWith opts $ buildUrl file
getResponse file Nothing = try $ (get $ buildUrl file)
我注意到304 (not modified)
響應回來作爲例外,這樣是我使用Either
類型的理由。我想爲可能使用此api包裝的人員提供可見性。
假設請求成功,我想將響應正文解析爲我的庫中定義的相應類型。如果在提出請求的服務器上發生了某些更改,則反序列化可能無法正常工作,因此我選擇使用Maybe
類型來解決此問題。
getPayload :: FromJSON b => (Either e (Response L.ByteString)) -> Either e (Maybe b)
getPayload (Left _) = return Nothing
getPayload (Right a) = return $ fmap Just (^. responseBody) =<< asJSON a
這些功能的特徵也開始像一個礙眼到我看來,東西在我的直覺告訴我有一個更好的方式,但我不確定。我做的一件事是做出另一個功能,把它們放在一起,希望它更容易使用。這是我計劃使用的功能來創建其他功能,以對個別資源進行更具體的請求。
getResource :: (Exception e, FormatTime t, FromJSON b) => File -> Maybe t -> IO (Either e (Maybe b))
getResource f t = getPayload <$> (getResponse f t)
我現在不得不在處理http請求時處理3層結構。 IO
,Either
和Maybe
。我是否讓這個過於複雜?從使用和可維護性的角度來看,我能做些什麼來減輕這種痛苦?我該如何改進?
難道你不能將'e(可能b)'變成''或e'',其中'e'還可以攜帶關於反序列化失敗的信息? '也許b'與'Either()b'同構。 –
我會考慮使用自定義數據類型'data ResourceResult b = Error e | NotModified |結果b'。圖書館總數和產品類型都很好,但是沒有任何風格:它們非常通用,不能傳達任何意義。最好使用具有適當名稱的自定義類型。 – chi
謝謝你的建議@chi。我會牢記這一點。 –