haskell - 如何在 Scotty Action 中使用 System.command

标签 haskell functional-programming monads

我正在尝试学习 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!

最佳答案

在 Haskell 中, do -notation用于链接类似语句的东西。语句是某种类型的构造函数,如 IO应用于特定的结果类型。例如,语句 system "ls"有类型 IO ExitCode .

IO 之外的其他类型构造函数可以作为语句使用。所有这些 do -notation 要求类型构造函数实现 Monad interface这解释了如何明智地链接语句。

然而,内单do -block,只允许一种类型的语句!他们必须都是 IO声明,或所有 ActionT Text IO声明。在您的示例中,您将两者混合在一起,这会导致错误。 Scotty's get 函数需要一个 ActionT Text IO 陈述:

get :: RoutePattern -> ActionM () -> ScottyM ()
-- ActionM is actually a synonym for ActionT Text IO

好消息是有一种方法可以转换(通常的 Haskell 术语是“提升”)IO声明成ActionT Text IO声明。后者实际上是 IO 之上的一种“装饰器”(通常的 Haskell 术语是 "monad transformer" )操作,启用与 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 那样——然后我们可以提升 |1046 | 声明到 IO 声明”。

以及 ActionT e m 的专用类型是:
liftIO :: IO a -> ActionT Text IO a

关于haskell - 如何在 Scotty Action 中使用 System.command,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58670103/

相关文章:

haskell - 相等的模式匹配

haskell - 创建我自己的状态 monad 转换器模块,隐藏底层状态 monad

haskell - 将表达式转换为无点样式(Haskell)

javascript - 2048 : Strange behaviour of reduceRight in map with lodash/fp

Java 8 函数式编程 - 需要在类上编写通用函数

functional-programming - java8流样式将键值列表转换为 map ?

haskell - ArrowLoop 是如何工作的?另外,mfix?

haskell - 并行 haskell 。对生产者进行速率限制

haskell - 如何编写更通用的 `Control.Monad.Writer.censor` 版本?

haskell - 有什么可生成的吗?