我正在处理我的第一个Haskell工具(耶!),但是我似乎找不到解决这个问题的方法。大多数文章讨论如何将String
转换为IO String
,但实际上我需要做相反的操作,因为我在mapM
中有条件地使用readFile
。
我确定有更好的方法来解决这个问题,但是这是我目前所拥有的。这解析了一个源文件(非相关语言)并用包含文件的实际内容替换#include
语句。
replaceInclude :: String -> IO String
replaceInclude contents = do
f_lines <- mapM
(\l ->
if (isInfixOf "#include" l)
then readFile (parseIncludePath l)
else l -- !! This is the problem line !!
)
(lines contents)
return (unlines f_lines)
正如在评论中指出的,问题出在else
语句上,它返回一个String
类型,但mapM
函数需要一个IO String
类型。
非常感谢任何帮助,我相信我必须以“Haskell方式”重新思考这个问题 :)
编译错误:
* Couldn't match type `[]' with `IO'
Expected type: IO String
Actual type: [Char]
pure
/return
(同一件事) - FrownyFrogimport Data.Traversable
,你可以写成f_lines <- for (lines contents) $ \l -> if ....
。for
大致上是将参数翻转的mapM
。 - chi$
和.
,但是还没有弄清它们的含义,你能简单解释一下吗? - scx$
是一个函数应用操作符:f $ x
表示f x
。它主要用于避免在某些情况下使用括号,例如f (g x y)
可以变成f $ g x y
。而.
则是函数组合:f . g
表示(\x -> f (g x))
。如果你是初学者,不必过于担心它们——一开始很容易误用并产生错误。上面,我建议在for
的最后一个参数中使用$
,因为它是多行的,避免使用括号看起来更好看。 - chi