【问题标题】:type of main function doesn't mean to my applicationmain 函数的类型对我的应用程序没有意义
【发布时间】:2016-04-25 14:45:03
【问题描述】:

我们知道 main 函数的类型为 IO ()。 但是,这对我来说是个问题,因为我的程序可能会返回错误。这意味着我正在从 main 函数执行类似的操作:

ErrorT String IO ()  

当然,此时我遇到了类型错误的问题。

我该怎么办?

args <- getArgs
s <- readFile $ head args
myFoo s

在哪里myFoo :: String -&gt; ErrorT String IO ()

【问题讨论】:

  • 顺便说一句,main 不是函数。这是一个动作。函数的特点是有参数。
  • @leftaroundabout 这对我来说听起来很奇怪,是在语言规范中吗? main 的类型签名表明它是一个值。 “动作”来自 IO monad 的内部魔法,对吧?你肯定不会打电话给x :: Int; x = 5 吗?
  • @kai:当然也是一个值。 Haskell 中的每一个“事物”都是一个值,包括函数和动作。只是,大多数值实际上不是函数,也不是动作。 action 一词的定义并不明确,它通常被理解为某种类型的值 M A 其中M 是一个单子。 IO () 肯定符合条件,Int 肯定没有!例如,是否会不太明确。 [True] 应该被视为一个动作。
  • 注意一下,main的类型是IO a
  • @DerekElkins,确实如此,但 IMO 始终最好将其修复为 IO ()IO Void 或多态 IO a(相当于 IO Void)。我选择后者之一表明程序只能作为异常的结果终止。

标签: haskell io monads


【解决方案1】:

你需要用runErrorT运行它:

runErrorT :: ErrorT e m a -> m (Either e a)

由于myFoo 返回ErrorT String IO (),这将评估为您在main 中执行的IO (Either String ()) 并匹配结果:

args <- getArgs
s <- readFile $ head args
result <- runErrorT (myFoo s)
case result of
  Right _ -> putStrLn "ok!"
  Left(err) -> putStrLn $ "Error: " ++ err

【讨论】:

    【解决方案2】:

    要扩展@Lee 的答案,您可以使用exitFailureexitSuccess 中的System.Exit 向调用进程返回适当的错误代码:

    module Main (main) where
    
    import Control.Monad.Error
    import System.Environment
    import System.Exit
    
    myFoo :: String -> ErrorT String IO ()
    myFoo = undefined
    
    main :: IO ()
    main = do
        args <- getArgs
        s <- readFile $ head args
        result <- runErrorT (myFoo s)
        case result of
            Right _ -> do
                putStrLn "OK"
                exitSuccess
            Left (e) -> do
                putStrLn $ "Error: " ++ e
                exitFailure
    

    【讨论】:

      猜你喜欢
      • 2015-12-11
      • 2013-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-11
      • 1970-01-01
      • 2018-06-12
      相关资源
      最近更新 更多