gpt4 book ai didi

Haskell Monads 和 liftIO 我不明白

转载 作者:行者123 更新时间:2023-12-05 04:53:30 24 4
gpt4 key购买 nike

您好社区,感谢您抽出宝贵时间。

我有一个错误,我不确定错误是什么,但我认为问题是:ext-1.2.4.1:Data.Text.Internal.Lazy.Text IO)没有IO变压器至 Web.Scotty.Internal.Types.ScottyT .

但我想知道为什么编译器使用 ext-1.2.4.1:Data.Text.Internal.Lazy.Text IO) .这就是为什么我只使用 String 并删除所有出现的 {-# LANGUAGE OverloadedStrings #-} 的原因但仍然出现错误。另一方面,这应该是 IO [String] ,不应该吗?正如你所说,我真的不知道是什么 ext-1.2.4.1:Data.Text.Internal.Lazy.Text IO)是。

在另一个地方,我已经使用了liftIO成功获得 a -> IO String功能。我想我以同样的方式使用它们。

我想我对 monad 是什么有了慢慢的感觉,但不太确定。 我真的不知道为什么我必须使用 lift完全发挥作用。

错误信息:

    • No instance for (MonadIO
(Web.Scotty.Internal.Types.ScottyT
text-1.2.4.1:Data.Text.Internal.Lazy.Text IO))
arising from a use of ‘liftIO’
• In a stmt of a 'do' block:
paths <- liftIO $ getAllFilePaths2 path
In the expression:
do paths <- liftIO $ getAllFilePaths2 path
pathsToScotty paths
In an equation for ‘pathsToScotty2’:
pathsToScotty2 path
= do paths <- liftIO $ getAllFilePaths2 path
pathsToScotty paths
|
49 | paths <- liftIO $ getAllFilePaths2 path

错误发生的地方:

import Control.Monad.IO.Class
...
pathsToScotty2 :: String -> ScottyM ()
pathsToScotty2 path = do
paths <- liftIO $ getAllFilePaths2 path
pathsToScotty paths

getAllFilePaths2 :: String -> IO [String]
getAllFilePaths2 dir = do
putStrLn dir
isFile <- doesFileExist dir
if isFile
then return [dir]
else do
dirs <- listDirectory dir
foldl foldHelper2 (return []) $ map (\d -> show $ mconcat [dir, "/",d ]) dirs


foldHelper2 :: IO [String] -> String -> IO [String]
foldHelper2 ps path = do
paths <- ps
newPaths <- getAllFilePaths2 path
return (paths ++ newPaths)

最佳答案

真正理解 monad 需要时间、练习和耐心,但通过检查您的类型来理解 liftIO 的需求应该不会太难。

首先,liftIO 的类型是 MonadIO m => IO a -> m a。这意味着该函数可以将任何 IO 操作转换为 monad m 中的操作,只要 m 具有 MonadIO 的实例。理论上,这只有在 m 有某种处理 IO Action 的方法时才能实现,所以这个函数是将给定的 Action 嵌入到 m 中单子(monad)。

liftIO 绝对适合您,但为什么它不起作用?也就是说,您有一个 IO [String] 类型的值 getAllFilePaths2 path,并且您希望它是 ScottyM [String]< 类型的值 — 这确实是使用 liftIO 的好地方。但是,ScottyM 不是 MonadIO 的实例,因为您看到的错误消息试图告诉您,所以您不能使用 liftIO

这可能看起来很疯狂——你真的不能将 IO 操作嵌入到 ScottyM 中吗?——但实际上这是有充分理由的。如果 IO 操作抛出错误会怎样?你的整个网络应用程序会崩溃吗?如果您天真地使用 liftIO,它就会出现。相反,scotty 提供了函数 liftAndCatchIO ,正如文档所描述的那样,它是“类似于 liftIO,但捕获任何 IO 异常并将它们转换为 Scotty 异常。”这是将 IO 操作嵌入 Scotty 的首选方式。

最后的问题来了:请注意,liftAndCatchIO 实际上生成类型为 ActionM a 的值,而不是 ScottyM a。此外,无法在 ActionM monad 中获取值并将其放入 ScottyM monad 中。相反,您需要将该值用作操作。所以,我不确定 pathsToScotty 的作用,但很可能您需要重写它。

关于Haskell Monads 和 liftIO 我不明白,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66043333/

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