我有一个工作正常的程序:
{-# 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.
如何解决我的问题?
<-
、>>=
或其他方式将其绑定。 - Mephy