我正在努力学习haskell中的语句是如何工作的。我试图制作一个非常简单的程序,您可以调用REST端点并执行一个系统命令(非常简单,比如"ls"),问题是将不同的操作类型组合在一个do语句中。
import Web.Scotty
import System.Cmd
main = do
putStrLn "Starting Server"
scotty 3000 $ do
get "/url" $ do
system "ls"
text "Success"但是我得到了下一个编译器错误:
Main.hs:12:7:
Couldn't match expected type ‘Web.Scotty.Internal.Types.ActionT
Data.Text.Internal.Lazy.Text IO a0’
with actual type ‘IO GHC.IO.Exception.ExitCode’
In a stmt of a 'do' block: system "ls"
In the second argument of ‘($)’, namely
‘do { system "ls";
text "Success" }’我在努力学习Haskell很难!
发布于 2019-11-02 10:41:31
在Haskell中,-notation用于链接类似语句的东西。语句是应用于特定结果类型的某种类型构造函数,如IO。例如,语句system "ls"的类型为IO ExitCode。
IO以外的其他类型构造函数可以作为语句工作。do-notation所需要的只是类型构造函数实现Monad 接口,这说明了如何明智地链接语句。
但是,在单个do-block中,只允许一种类型的语句!它们必须是所有IO语句,或所有ActionT Text IO语句。在您的示例中,您将两者混合在一起,这将导致错误。Scotty的get函数需要一个ActionT Text IO语句:
get :: RoutePattern -> ActionM () -> ScottyM ()
-- ActionM is actually a synonym for ActionT Text IO好消息是,有一种方法可以将IO语句转换为ActionT Text IO语句(通常的Haskell术语是"lift")。后者实际上是IO操作的一种“修饰器”(通常Haskell术语是IO),它支持与Scotty相关的额外功能。您可以使用IO函数将liftIO操作“提升”到装饰器中,如下所示:
get "/url" $ do
liftIO (system "ls")
text "Success"通常,何时可以使用liftIO将普通的IO语句提升为“修饰”语句?“装饰器”类型构造函数除了通常的MonadIO实例之外,还必须有一个Monad实例。MonadIO提供了liftIO函数。
在我们的例子中,查看ActionT的可用实例
(MonadIO m, ScottyError e) => MonadIO (ActionT e m)这意味着“如果m是有一个MonadIO实例--就像IO做的一样--而错误类型e有一个ScottyError实例--就像Text一样--那么我们可以将IO语句提升到ActionT e m语句”。
liftIO的专门类型是:
liftIO :: IO a -> ActionT Text IO ahttps://stackoverflow.com/questions/58670103
复制相似问题