字符串到 IO 字符串(条件 mapM)

String to IO String (conditional mapM)

提问人:scx 提问时间:7/24/2022 更新时间:7/25/2022 访问量:145

问:

我正在开发我的第一个 Haskell 工具(耶!),但我似乎找不到解决这个问题的方法。大多数帖子都讨论将 a 转换为 ,但我实际上需要做相反的事情,因为我有条件地在 里面使用 。StringIO StringreadFilemapM

我相信有更好的方法可以做到这一点,但这是我目前所得到的。这将解析源文件(不相关的语言),并将语句替换为包含文件的实际内容。#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)

如注释中所述,问题行是语句,它返回 ,但期望 .elseStringmapMIO String

任何帮助将不胜感激,我相信我必须重新连接我的大脑才能以“haskell方式”做到这一点:)

编译错误:

* Couldn't match type `[]' with `IO'
  Expected type: IO String
    Actual type: [Char]
字符串 哈斯克尔 io

评论

2赞 FrownyFrog 7/24/2022
尝试 / (同样的事情)purereturn
0赞 scx 7/24/2022
@FrownyFrog哈哈,我刚刚想通了,这么简单。已回答:)
2赞 chi 7/24/2022
如果你,你可以写 . 大致是与论点翻转。import Data.Traversablef_lines <- for (lines contents) $ \l -> if ....formapM
0赞 scx 7/25/2022
@chi!我能问一下,我已经在很多地方看到和使用过,但还没有明白它们的含义,你能对它们有一个快速的解释吗?$.
1赞 chi 7/25/2022
$是一个函数应用程序运算符:表示。在某些情况下,它主要用于避免使用括号,例如 成为。取而代之的是函数组合:意味着。如果您是初学者,请不要太担心它们 - 一开始很容易误用它们并获得错误。上面,我建议使用最后一个参数,因为它是多行的,避免括号看起来不错。f $ xf xf (g x y)f $ g x y.f . g(\x -> f (g x))$for

答:

2赞 scx 7/24/2022 #1

天哪,这太简单了,解决方案是.else return l

对于后代和其他初学者: 在 Haskell 中,该函数创建一个标记类型。之所以如此,是因为原因。A Gentle Introduction to Haskell 中的文档非常有用且清晰。returnIO

评论

3赞 chepner 7/24/2022
在此上下文中,生成一个值,因为您正在使用 monad。 适用于所有单子。例如,等。returnIO StringIOreturnreturn 3 :: Maybe Int == Just 3return 3 :: [Int] == [3]