gpt4 book ai didi

function - 如何在 Haskell 中从 a -> IO b 生成 IO (a->b) 函数

转载 作者:行者123 更新时间:2023-12-02 22:12:58 25 4
gpt4 key购买 nike

我想编写一个函数,可以在 Haskell 中以广度优先的方式递归列出目录。正如你所看到的,我需要一个可以将 a (a -> IO b) 转换为 IO (a->b) 的函数。看似简单,我却做不到。我想知道该怎么做或者是否可能。

dirElem :: FilePath -> IO [FilePath]
dirElem dirPath = do
getDirectoryContents'' <- theConvert getDirectoryContents'
return $ takeWhile (not.null) $ iterate (concatMap getDirectoryContents'') [dirPath] where
getDirectoryContents' dirPath = do
isDir <- do doesDirectoryExist dirPath
if isDir then dirContent else return [] where
dirContent = do
contents <- getDirectoryContents dirPath
return.(map (dirElem</>)).tail.tail contents
theConvert :: (a -> IO b) -> IO (a -> b)
theConvert = ??????????

最佳答案

这是无法完成的。原因是该函数可以使用其a类型的参数来确定执行什么IO操作。考虑一下

action :: Bool -> IO String
action True = putStrLn "Enter something:" >> getLine
action False = exitFailure

现在,如果您以某种方式将其转换为 IO (Bool -> String) 并评估此操作,会发生什么?没有解决办法。我们无法决定是否应该读取字符串或退出,因为我们还不知道 Bool 参数(如果没有在参数上调用结果函数,我们可能永远不会知道它)。

约翰的回答是一个主意。它只是让 IO 操作转入纯粹的计算,这会让你的生活变得悲惨,并且你将失去 Haskell 的引用透明度!例如运行:

main = unsafe action >> return ()

即使调用了 IO 操作,也不会执行任何操作。此外,如果我们稍微修改一下:

main = do
f <- unsafe action
putStrLn "The action has been called, calling its pure output function."
putStrLn $ "The result is: " ++ f True

您将看到请求输入的action是在调用f内部以纯计算执行的。您无法保证该操作何时(如果有的话)执行!

编辑:正如其他人指出的那样,它不仅仅特定于IO。例如,如果 monad 是 Maybe,则无法实现 (a -> Maybe b) -> Maybe (a -> b)。或者对于 Either,您无法实现 (a -> Either c b) -> Either c (a -> b)。关键始终是,对于 a -> m b,我们可以根据 a 选择不同的效果,而在 m (a -> b) 中,效果必须是固定的。

关于function - 如何在 Haskell 中从 a -> IO b 生成 IO (a->b) 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14432883/

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