gpt4 book ai didi

haskell - IO 上的 mapM 产生无限输出

转载 作者:行者123 更新时间:2023-12-01 07:23:29 26 4
gpt4 key购买 nike

这是一种奇怪的行为,即使对 Haskell 来说也是如此。看下面的代码段:

import System.Directory
import System.FilePath

-- This spins infinitely
loadCtx :: FilePath -> IO ()
loadCtx dir = do
lsfiles <- listDirectory dir
let files = mapM (dir </>) lsfiles
putStrLn $ "Files " ++ show files

-- This does what I'd expect, prepending the dir path to each file
loadCtx dir = do
lsfiles <- listDirectory dir
let files = map (dir </>) lsfiles
putStrLn $ "Files " ++ show files

两种定义都从类型检查器中接受,但完全给出
不同的行为。第一个 mapM 的输出是什么?读取某些文件时看起来像是一个无限循环。也可以组成 listDirectory带有 map (dir </>) 的箭头线在一行中预先设置路径?

最佳答案

What is the output of the first mapM? It looks like an infinite loop on reading some files.



这不是一个无限循环——只是一个非常非常长的循环。

您没有使用 mapM对于 IO ;您正在使用 mapM在非确定性单子(monad)中。这是 mapM 的类型,专门针对那个单子(monad):
Traversable t => (a -> [b]) -> t a -> [t b]

请按以下方式阅读:
  • 首先,给我一种将容器的元素(类型 a )转换为许多可能的替换元素(类型 [b] )之间的非确定性选择的方法。
  • 然后给我一个容器的元素(类型 t a )。
  • 我将在其中包含替换元素的容器(类型 [t b])之间为您提供一个不确定的选择。 (而且,这部分不在类型中,而是:我将采用所有可能的组合来实现这一点;对于容器中的每个位置,我将尝试每个可能的 b ,并为您提供每种可能的方式为容器中的每个位置做出一个选择。)

  • 例如,如果我们要定义函数 f :: Int -> [Char] f n在第一个 n 之间不确定地选择字母表中的字母,然后我们可以看到这种交互:
    > f 3
    "abc"
    > f 5
    "abcde"
    > f 2
    "ab"
    > mapM f [3,5,2]
    ["aaa","aab","aba","abb","aca","acb","ada","adb","aea","aeb","baa","bab","bba","bbb","bca","bcb","bda","bdb","bea","beb","caa","cab","cba","cbb","cca","ccb","cda","cdb","cea","ceb"]

    在每个结果中,第一个字母是字母表中的前三个(a、b 或 c)之一;第二个来自前五个,第三个来自前两个。更重要的是,我们得到了每个具有这个属性的列表。

    现在让我们考虑一下这对您的代码意味着什么。你写
    mapM (dir </>) lsfiles

    所以你会得到一个列表的集合。集合中的每个列表将与 lsfiles 一样长是。让我们关注集合中的一个列表;叫它 cs .
    cs 的第一个元素将从 dir </> filename 中抽取, 其中 filenamelsfiles 的第一个元素;也就是说,它将是 dir 中的字符之一, 或斜线, 或 filename 中的字符之一. cs 的第二个元素将类似: dir 的字符之一, 或斜线, 或 lsfiles 中第二个文件名中的字符之一.我想你可以看到这是怎么回事......这里有很多可能性。 =)

    Also is it possible to compose the listDirectory do-arrow line with the map (dir </>) that prepends the path, in one-line?



    是的:
    loadCtx dir = do
    files <- map (dir </>) <$> listDirectory dir
    putStrLn $ "Files " ++ show files

    关于haskell - IO 上的 mapM 产生无限输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53786788/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com