Haskell 中的 IO 操作映射

Mapping with IO actions in Haskell

我有一个函数,它接受两个文件名,并将这两个文件的内容读入 Strings,然后 returns 如果它们匹配或不匹配。这是函数:

f :: String -> String -> IO Bool
f fileName1 fileName2 = do
        str1 <- readFile fileName1
        str2 <- readFile fileName2
        return (str1 == str2)

如果我从内部这样使用它 main:

main = do
        res <- f "A.txt" "B.txt"
        print res

它可以工作并打印 TrueFalse。我想要做的是,将此函数 f 应用于文件名列表(元组)。例如:

[("a.txt", "b.txt"), ("c.txt", "d.txt")]

(假设a.txtb.txt内容相同,c.txtd.txt不同)

我想将其(文件名列表)转换为 Bool 列表,例如:[True, False]。我尝试使用 mapM,但似乎没有映射任何内容(当我在使用 mapM 后打印列表时,它打印相同的元组列表)。

所以我的问题是:我做错了什么,我怎样才能像上面提到的那样获得 Bool 的列表?

请放轻松,因为我对 Haskell 和函数式编程还很陌生 :)

这是一个函数 f' 可以执行您描述的操作。

f' :: [(String,String)] -> IO [Bool]
f' = mapM $ uncurry f

如果有什么不清楚的地方,请告诉我!而且,为了清楚起见,以下是您如何 运行 它:

main = do
        res <- f' [("a.txt", "b.txt"), ("c.txt", "d.txt")]
        print res

编辑

函数是无点形式的,所以等价于f' lst = mapM (uncurry f) lstmapM 实质上是使用 f 作为函数映射 lst 的每个元素,并将 IO 推到列表外部。

uncurry 只是采用 a -> b -> c 形式的函数并将其转换为一个 (a,b) -> c,这是我们想要的,因为您有一个元组列表。