我正在研究我在这里工作的项目:
我在我的函数中使用monad变换器方法看起来像这样:
scrapePost :: String -> IO ()
scrapePost url = liftM (fromMaybe ()) . runMaybeT $ do
doc <- lift $ fromUrl url
-- get a bunch of stuff from the page
-- send it to the db
replies <- lift . runX $ doc >>> css ".post.reply"
-- here is the problem
mapM_ (parseReply url (fromJust page_id)) replies
-- here is the problem
Run Code Online (Sandbox Code Playgroud)
parseReply 是我需要的功能,但我似乎无法做到正确.
这是我开始这个功能的微弱尝试:
parseReply :: String -> String -> XNode -> Maybe ()
parseReply url op_id reply = do
reply_id <- runX $ reply ! "id"
return ()
Run Code Online (Sandbox Code Playgroud)
顺便说一下,我正在使用HandsomeSoup
我将像scrapePost使用set css规则的函数一样操作,删除没有所有值的回复,并将它们发送到db.
我想用mapM,因为我的希望是,以取代所有mapM与liftIO看到的性能差异.
[UPDATE]
所以事实证明我不需要做任何类型的杂技,我只需要一种方法将回复节点变成我在这里找到的根节点.
由于parseReply仅在MaybeT IO ()上下文中使用,因此其类型不需要更改并且scrapePost可以保持不变.
parseReply 变为:
toRoot :: ArrowXml a => XmlTree -> a n XmlTree
toRoot node = root [] [constA node]
parseReply :: String -> String -> XmlTree -> MaybeT IO ()
parseReply url op_id reply = do
let node = toRoot reply
reply_id <- lift . liftM (`atMay` 0) $ runX $ node >>> css "div" ! "id"
guard (isJust reply_id)
return ()
Run Code Online (Sandbox Code Playgroud)
让我们来看看你的"monad runner"的类型
liftM (fromMaybe ()) . runMaybeT :: MaybeT IO () -> IO ()
Run Code Online (Sandbox Code Playgroud)
所以我们需要do块的每一行都有类型MaybeT IO ().由于mapM_ :: (a -> m b) -> [a] -> m ()我们parseReply url (fromJust page_id)需要有型MaybeT IO ()不只是Maybe ().
幸运的是,正如人们所希望的那样,很容易注入纯粹的Maybe东西MaybeT IO
parseReplyT :: Monad m => String -> String -> XNode -> MaybeT m ()
parseReplyT url op_id = MaybeT . return . parseReply url op_id
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
139 次 |
| 最近记录: |