Nic*_*sta 6 haskell types functional-programming wreq
我是Haskell初学者,目前正在使用wreq围绕api制作一个简单的包装器.if-modified-since
如果提供时间,我想发送标题.我是按照以下方式这样做的.
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)
Run Code Online (Sandbox Code Playgroud)
我注意到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
Run Code Online (Sandbox Code Playgroud)
这些功能的签名开始对我来说似乎是一个眼睛,我的直觉告诉我有更好的方法,但我不确定.我做的一件事是制作另一个功能,将它们放在一起,希望它更容易使用.这是我计划用于创建其他函数以对单个资源发出更具体请求的函数.
getResource :: (Exception e, FormatTime t, FromJSON b) => File -> Maybe t -> IO (Either e (Maybe b))
getResource f t = getPayload <$> (getResponse f t)
Run Code Online (Sandbox Code Playgroud)
在处理http请求时,我现在必须处理3层结构. IO
,Either
和Maybe
.我这太复杂了吗?从使用和可维护性的角度来看,我能做些什么来减少这种痛苦?我怎样才能改善这个?
这可能不是您想要的,但asJSON
返回类型为m (Response a)
,其中m
是MonadThrow
。WhileMaybe
是一个MonadThrow
实例,那么 也是Either e
。这意味着您不必使用来Maybe
处理asJSON
. 你可以“留在” Either
monad 中:
getPayload :: FromJSON b => Either SomeException (Response L.ByteString)
-> Either SomeException b
getPayload = ((fmap (^. responseBody) . asJSON) =<<)
Run Code Online (Sandbox Code Playgroud)
显然,这对左侧的错误类型施加了额外的限制,因此我不确定这是可以接受的。如果没有,请发表评论。