【发布时间】:2014-03-15 23:05:45
【问题描述】:
我已经玩了一段时间 Haskell,但我还没有完全掌握如何使用在 Monad 中运行的第三方函数。每次我回去阅读有关 Monads 等的文章时,我都会得到很好的理解,但是在将它们应用于实际代码时,我无法理解为什么一段代码不起作用。我采用反复试验,通常会编译它,但我觉得我应该能够在第一次正确使用它们而无需尝试通过我的启发式更改(尝试 let, <-, liftM, 等)
所以我想根据这个简单的功能提出几个问题,诚然它做了很多有趣的事情。
import Text.XML.HXT.Core
import Text.HandsomeSoup
import Data.String.Utils
function h = do
let url = myUrlBuilder h
doc = fromUrl url
res = runX $ doc >>> css "strong" /> getText
--nres = liftM rmSpaceAndBang (res)
res
rmSpaceAndBang ps = map (\x-> replace "!" "" (strip x)) ps
上面的代码编译。我故意省略了类型声明,因为我认为它应该是不编译的。所以这是我的问题。
为什么我不能这样做 res <- runX ... 并以这种方式返回 res?
为什么res 应该在一个 let 语句中,而不是绑定到操作的结果?据我了解,do x <- a1; a2 等同于a1 >>= \x -> a2。当您let x = a1 时,这有什么不同?
当我使用<- 时出现以下错误,如果不是我的反复试验方法,我将无法确定我需要在这里使用let。
Couldn't match type `[]' with `IO'
Expected type: IO String
Actual type: [String]
虽然我专注于上面的res,但我缺乏理解也适用于函数中的其他let 语句。
如何找到res的返回类型?
我想不出一种在 hackage 中搜索 getText 的方法(hxt 似乎太大而无法逐个模块地查看。下次可能会尝试使用 Google 站点搜索)。最后,我最终在 GHCi 中输入了部分代码并输入了:t res。它告诉我它是[String]。有一个更好的方法吗?
由于 res 是 [String] 类型,我想我会将 [String] 作为函数的返回类型。但 GHC 说它应该是IO [String](编译)。为什么:t先给我错误的信息?
当函数返回IO String时,对它们使用纯函数的最佳方式是什么?
现在我被困在IO [String] 里面,我需要用它来提升我进行字符串操作的任何地方。有没有更好的方法来做到这一点?
希望我能从中学到足够的知识,以便能够使用正确的语法,而不必盲目地尝试一些组合。
更新:
我缺少的关键部分是res 不是一个值,而是一个动作。所以我有两个选择:一个是我上面的代码let res =,但最后调用它,另一个是做res <-,然后做return (res)。
使用res <- 的优点是我可以摆脱liftM,因为res 现在是[String](请参阅下面@duplode 的答案)。
谢谢!
【问题讨论】:
-
在Hackage中搜索特定功能,请尝试使用Hayoo:holumbus.fh-wedel.de/hayoo/hayoo.html它也支持签名搜索。
-
谢谢@DanielDíazCarrete,当我在Hayoo 中做
hxt getText时,马上就找到了这个功能! getText 的返回类型为a XmlTree String。我看到runX有这种类型IOSArrow XmlTree c -> IO [c]。我现在了解如何获得 IO [String]。 -
let x = a1 ...非常像(\x -> ...) a1,而不是<-变成的。 -
你甚至可以不使用
res,只需将runX $ doc >>> css "strong" /> getText放在let 绑定之后。
标签: haskell