gpt4 book ai didi

Haskell 从 do-Block 中生成函数

转载 作者:行者123 更新时间:2023-12-02 16:35:54 27 4
gpt4 key购买 nike

我有以下运行良好的程序:

{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE ScopedTypeVariables #-}

module GPS where

import Network.Wreq
import Control.Lens
import Text.HTML.TagSoup
import Data.ByteString.Lazy
import Data.ByteString.Lazy.Char8
import Data.Strings

getStr :: Tag ByteString -> String
getStr tag@(TagText str) = Data.ByteString.Lazy.Char8.unpack str
getStr _ = ""

filterStr :: [Tag ByteString] -> [String]
filterStr [] = []
filterStr (t:r) = [getStr t] ++ filterStr r

main :: IO ()
main = do
r <- post "http://www.geocodeip.com" ["IP" := Data.ByteString.Lazy.Char8.pack "79.212.82.103"]
html <- r ^. responseBody
let tags = parseTags html
let tr = Prelude.head $ sections (~== ("<tr>" :: String)) tags
let tag = Prelude.filter isTagText tr
let text = filterStr tag
let ztext =Prelude.zip [0..] text
let nlat = Prelude.head $ Prelude.map fst . Prelude.filter (\(_, str) -> strEq str ("Latitude:" :: String)) $ ztext
let nlng = Prelude.head $ Prelude.map fst . Prelude.filter (\(_, str) -> strEq str ("Longitude:" :: String)) $ ztext
let lat = read (Prelude.head $ Prelude.map snd . Prelude.filter (\(n, _) -> n == nlat + 1) $ ztext) :: Double
let lng = read (Prelude.head $ Prelude.map snd . Prelude.filter (\(n, _) -> n == nlng + 1) $ ztext) :: Double
print lat
print lng

现在有趣的部分 - 我想从这个“do-Block”中创建子功能,例如getHTML、getTags、makeText 等...

所以我开始做以下事情:

getHTML :: String -> IO ByteString
getHTML ip = fmap (view responseBody) (post "http://www.geocodeip.com" ["IP" := Data.ByteString.Lazy.Char8.pack ip])

这应该替换我的 do-Block 的第一行和第二行,它应该获取 HTML。这工作正常,唯一的问题是它使用 IO 重新调整类型,因此 let Tags = parseTags $ getHTML "79.212.82.103" 不起作用:

[1 of 1] Compiling GPS              ( GPS.hs, interpreted )

GPS.hs:38:14:
No instance for (Text.StringLike.StringLike (IO ByteString))
arising from a use of ‘parseTags’
In the expression: parseTags
In the expression: parseTags $ getHTML "79.212.82.103"
In an equation for ‘tags’:
tags = parseTags $ getHTML "79.212.82.103"

GPS.hs:39:37:
No instance for (Text.StringLike.StringLike (IO ByteString))
arising from a use of ‘~==’
In the first argument of ‘sections’, namely
‘(~== ("<tr>" :: String))’
In the second argument of ‘($)’, namely
‘sections (~== ("<tr>" :: String)) tags’
In the expression:
Prelude.head $ sections (~== ("<tr>" :: String)) tags

GPS.hs:41:24:
Couldn't match type ‘IO ByteString’ with ‘ByteString’
Expected type: [Tag ByteString]
Actual type: [Tag (IO ByteString)]
In the first argument of ‘filterStr’, namely ‘tag’
In the expression: filterStr tag
Failed, modules loaded: none.

如何解决我的问题?

最佳答案

现在这是一个单子(monad)操作,所以使用单子(monad)语法:

tags <- parseTags <$> getHTML "79.212.82.103"
-- ⩓ ⩓
-- ╰─────────────│────────── bind instead of 'let'
-- ╰─────────────────── functor application

<$>只是中缀 fmap 。您可以在 getHTML 的实现中使用它也是如此。

关于Haskell 从 do-Block 中生成函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34184413/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com