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

时间:2012-06-03 01:41:50

标签: 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

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?

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

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

case checkStatus status of
   True -> monadTime >>= return . Just . processItPurely
   _    -> return Nothing

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

2 个答案:

答案 0 :(得分:27)

if块中缩进do - 表达式的“正确”方法是缩进elsethen行,而不是if。 ,像这样。

function = do
   monadFun
   yaySomeIO
   status <- maybeItWillFail
   if checkStatus status  -- Did we succeed?
      then monadTime >>= return . Just . processItPurely
      else return Nothing

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

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

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

答案 1 :(得分:6)

这不是您问题的直接答案,但您可以利用MaybeT来消除if语句。此外,foo >>= return . barbar <$> foo相同。 (<$>来自Control.Applicative,与fmap

相同
function :: MaybeT IO Whatever
function = do
   lift monadFun
   lift yaySomeIO
   status <- lift maybeItWillFail
   guard (checkStatus status)
   processItPurely <$> lift monadTime

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