条件中的Monadic表达式 - GHC编译,阴谋拒绝

Col*_*ury 15 haskell cabal

在这一个人的头上划了一天.

我的代码中有一些函数看起来像这样:

function :: IO (Maybe Whatever)
function = do
   monadFun
   yaySomeIO
   status <- maybeItWillFail
   if checkStatus status  -- Did we succeed?
   then monadTime >>= return . Just . processItPurely
   else return Nothing
Run Code Online (Sandbox Code Playgroud)

ghci将以交互方式加载和运行它,没有任何问题,ghc将愉快地编译它.然而,通过cabal运行这个给了我:

myProgram.hs:94:16:
Unexpected semi-colons in conditional:
    if checkStatus status; then monadTime >>= return . Just . processItPurely; else return Nothing

Perhaps you meant to use -XDoAndIfThenElse?
Run Code Online (Sandbox Code Playgroud)

无论这个-XDoAndIfThenElse选项是什么,我似乎无法在任何文档中的任何地方找到它的痕迹.为什么是cabal(或者就此而言,这是什么?)对我使用IT首先放置的分号大吼大叫?或者在if-then-else语句中使用monadic表达式只是一个坏主意?

请注意,cabal根本没有抱怨这个:

case checkStatus status of
   True -> monadTime >>= return . Just . processItPurely
   _    -> return Nothing
Run Code Online (Sandbox Code Playgroud)

...除了这是丑陋的地狱,我永远不想把它放在我的代码中.谁能告诉我发生了什么事?请提前感谢.

ham*_*mar 27

缩进的"正确"的方式if在-expressions do-块是缩进elsethen更多的行比if,像这样.

function = do
   monadFun
   yaySomeIO
   status <- maybeItWillFail
   if checkStatus status  -- Did we succeed?
      then monadTime >>= return . Just . processItPurely
      else return Nothing
Run Code Online (Sandbox Code Playgroud)

这是因为do块中具有相同缩进量的行通常被视为单独的语句.

但是,有一个扩展称为DoAndIfThenElse允许您按照您的方式编写它.此扩展在Haskell 2010中已成为标准,这就是为什么GHC默认启​​用它.

Cabal往往要求您更明确地了解这些事情,因此要在Cabal中使用它,您需要在.cabal文件中提及它或添加{-# LANGUAGE DoAndIfThenElse #-}到模块的顶部.

  • 谢谢,我会根据需要添加缩进! (3认同)

Dan*_*ton 6

这不是您问题的直接答案,但您可以通过利用来消除if语句MaybeT.另外,foo >>= return . bar是一样的bar <$> foo.(<$>来自Control.Applicative,和是一样的fmap)

function :: MaybeT IO Whatever
function = do
   lift monadFun
   lift yaySomeIO
   status <- lift maybeItWillFail
   guard (checkStatus status)
   processItPurely <$> lift monadTime
Run Code Online (Sandbox Code Playgroud)

唯一令人烦恼的是无偿洒水lift,但有办法摆脱这些.