Haskell卷曲帮助

Ina*_*thi 5 curl haskell types type-conversion

好吧,我正试图在Haskell中围绕IO,我想我会写一个处理网页的小应用程序来做它.我越来越绊倒在是片段(与道歉bobince,虽然是公平的,我不试图解析此HTML,只提取一个或两个值):

titleFromUrl url = do
    (_, page) <- curlGetString url [CurlTimeout 60]   
    matchRegex (mkRegexWithOpts "<title>(.*?)</title>" False True) page
Run Code Online (Sandbox Code Playgroud)

上面应该采用字符串形式的URL,扫描它指向的页面matchRegex,然后返回Nothing或者Just [a],a匹配(可能是多行)字符串.令人沮丧的是,当我尝试做的时候

Prelude> (_, page) <- curlGetString url [CurlTimeout 60]
Prelude> matchRegex (mkRegexWithOpts "<title>(.*?)</title>" False True) page
Run Code Online (Sandbox Code Playgroud)

在翻译中,它正是我想要的.当我尝试加载相同的表达式,并imports从文件关联时,它给我一个类型推断错误,说明它couldn't match expected type 'IO b' against inferred type 'Maybe [String]'.这告诉我,我错过了一些小而基本的东西,但我无法弄清楚是什么.我已经尝试过显式地转换page为字符串,但这只是迷信编程(并且它在任何情况下都不起作用).

任何提示?

luq*_*qui 8

是的,GHCi接受任何价值.你可以说:

ghci> 4
4
ghci> print 4
4
Run Code Online (Sandbox Code Playgroud)

但这两个值(4print 4)显然不相等.神奇的GHC正在做的是,如果你输入的内容评估为a IO something然后它执行该动作(如果something不是则打印结果()).如果没有,则调用show该值并打印出来.无论如何,你的程序无法访问这个魔法.

当你说:

do foo <- bar :: IO Int
   baz
Run Code Online (Sandbox Code Playgroud)

baz预计是类型IO something,否则是类型错误.这将允许您执行I/O然后返回纯值.你可以检查一下,注意到上述产量:

bar >>= (\foo -> baz)
Run Code Online (Sandbox Code Playgroud)

-- (specializing to IO for simplicity)
(>>=) :: IO a -> (a -> IO b) -> IO b
Run Code Online (Sandbox Code Playgroud)

因此

bar :: IO a
foo :: a
baz :: IO b
Run Code Online (Sandbox Code Playgroud)

修复它的方法是使用以下return函数将返回值转换为IO值:

return :: a -> IO a  -- (again specialized to IO)
Run Code Online (Sandbox Code Playgroud)

那么你的代码是:

titleFromUrl url = do
    (_, page) <- curlGetString url [CurlTimeout 60]   
    return $ matchRegex (mkRegexWithOpts "<title>(.*?)</title>" False True) page
Run Code Online (Sandbox Code Playgroud)

对于大多数上述讨论的,可以替代任何单子IO(例如Maybe,[]...),它仍然是真实的.