提问人:scx 提问时间:7/24/2022 更新时间:7/25/2022 访问量:145
字符串到 IO 字符串(条件 mapM)
String to IO String (conditional mapM)
问:
我正在开发我的第一个 Haskell 工具(耶!),但我似乎找不到解决这个问题的方法。大多数帖子都讨论将 a 转换为 ,但我实际上需要做相反的事情,因为我有条件地在 里面使用 。String
IO String
readFile
mapM
我相信有更好的方法可以做到这一点,但这是我目前所得到的。这将解析源文件(不相关的语言),并将语句替换为包含文件的实际内容。#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]
答:
2赞
scx
7/24/2022
#1
天哪,这太简单了,解决方案是.else return l
对于后代和其他初学者:
在 Haskell 中,该函数创建一个标记类型。之所以如此,是因为原因。A Gentle Introduction to Haskell 中的文档非常有用且清晰。return
IO
评论
3赞
chepner
7/24/2022
在此上下文中,生成一个值,因为您正在使用 monad。 适用于所有单子。例如,等。return
IO String
IO
return
return 3 :: Maybe Int == Just 3
return 3 :: [Int] == [3]
评论
pure
return
import Data.Traversable
f_lines <- for (lines contents) $ \l -> if ....
for
mapM
$
.
$
是一个函数应用程序运算符:表示。在某些情况下,它主要用于避免使用括号,例如 成为。取而代之的是函数组合:意味着。如果您是初学者,请不要太担心它们 - 一开始很容易误用它们并获得错误。上面,我建议使用最后一个参数,因为它是多行的,避免括号看起来不错。f $ x
f x
f (g x y)
f $ g x y
.
f . g
(\x -> f (g x))
$
for