pen*_*142 5 monads haskell lifting io-monad scotty
您好社区,感谢您的宝贵时间。
\n我有一个错误,我不确定错误是什么,但我认为问题是:\n没有从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]
,不是吗?\n正如你所提到的,我真的不知道是什么ext-1.2.4.1:Data.Text.Internal.Lazy.Text IO)
。
在另一个地方,我已经liftIO
成功使用了一个a -> IO String
函数。我想我也以同样的方式使用它们。
我想我慢慢地感觉到了 monad 是什么,但不太确定。我真的不知道为什么我必须使用一个lift
函数。
错误信息:
\n \xe2\x80\xa2 No instance for (MonadIO\n (Web.Scotty.Internal.Types.ScottyT\n text-1.2.4.1:Data.Text.Internal.Lazy.Text IO))\n arising from a use of \xe2\x80\x98liftIO\xe2\x80\x99\n \xe2\x80\xa2 In a stmt of a \'do\' block:\n paths <- liftIO $ getAllFilePaths2 path\n In the expression:\n do paths <- liftIO $ getAllFilePaths2 path\n pathsToScotty paths\n In an equation for \xe2\x80\x98pathsToScotty2\xe2\x80\x99:\n pathsToScotty2 path\n = do paths <- liftIO $ getAllFilePaths2 path\n pathsToScotty paths\n | \n49 | paths <- liftIO $ getAllFilePaths2 path\n\n
Run Code Online (Sandbox Code Playgroud)\n发生错误的地方:
\n \xe2\x80\xa2 No instance for (MonadIO\n (Web.Scotty.Internal.Types.ScottyT\n text-1.2.4.1:Data.Text.Internal.Lazy.Text IO))\n arising from a use of \xe2\x80\x98liftIO\xe2\x80\x99\n \xe2\x80\xa2 In a stmt of a \'do\' block:\n paths <- liftIO $ getAllFilePaths2 path\n In the expression:\n do paths <- liftIO $ getAllFilePaths2 path\n pathsToScotty paths\n In an equation for \xe2\x80\x98pathsToScotty2\xe2\x80\x99:\n pathsToScotty2 path\n = do paths <- liftIO $ getAllFilePaths2 path\n pathsToScotty paths\n | \n49 | paths <- liftIO $ getAllFilePaths2 path\n\n
Run Code Online (Sandbox Code Playgroud)\nimport Control.Monad.IO.Class\n...\npathsToScotty2 :: String -> ScottyM ()\npathsToScotty2 path = do\n paths <- liftIO $ getAllFilePaths2 path\n pathsToScotty paths\n\n
Run Code Online (Sandbox Code Playgroud)\n
liftIO
真正理解 monad 需要时间、练习和耐心,但通过检查类型来理解其需求应该不会太难。
首先, 的类型liftIO
是MonadIO m => IO a -> m a
。这意味着m
只要m
有 的实例,该函数就可以将任何 IO 操作转换为 monad 中的操作MonadIO
。理论上,这只有在m
有某种处理IO
动作的方式时才能实现,因此该函数将给定的动作嵌入到 monad 中m
。
您肯定是在正确的地方使用liftIO
,那么为什么它不起作用呢?也就是说,您有一个getAllFilePaths2 path
类型为 的值IO [String]
,并且您希望它是一个ScottyM [String]
\xe2\x80\x94 类型的值,这确实看起来是一个使用 的好地方liftIO
。但是,ScottyM
不是的实例MonadIO
,因为您看到的错误消息试图告诉您,因此您不能使用liftIO
.
这可能看起来很疯狂\xe2\x80\x94你真的不能将IO操作嵌入到\ xe2\x80\x94中ScottyM
吗?\xe2\x80\x94但这实际上是有充分理由的。IO
如果操作抛出错误会发生什么?您的整个网络应用程序崩溃了吗?如果你天真地使用liftIO
. 相反,scotty 提供了函数liftAndCatchIO
,正如文档所描述的那样,它“类似于liftIO
,但捕获任何 IO 异常并将其转换为 Scotty 异常”。IO
这是将动作嵌入到 Scotty 中的首选方式。
最后的问题来了:请注意,liftAndCatchIO
实际上生成的是 类型的值ActionM a
,而不是ScottyM a
。此外,无法获取ActionM
monad 中的值并将其放入ScottyM
monad 中。相反,您需要将该值用作操作。所以,我不确定它的pathsToScotty
作用是什么,但您很可能需要重写它。