Haskell 如何避免do符号中的多余变量?

Haskell 如何避免do符号中的多余变量?,haskell,do-notation,Haskell,Do Notation,假设在Haskell do符号块中,我希望有一个变量is_root指示我是否为root: import System.Posix.User main = do uid <- getRealUserID is_root <- return $ uid == 0 但这当然不会编译 如何去除多余的变量,如uid?以下是我想到的最好的: import System.Posix.User main = do is_root <- getRealUserID &g

假设在Haskell do符号块中,我希望有一个变量
is_root
指示我是否为root:

import System.Posix.User
main = do
    uid <- getRealUserID
    is_root <- return $ uid == 0
但这当然不会编译

如何去除多余的变量,如
uid
?以下是我想到的最好的:

import System.Posix.User
main = do
    is_root <- getRealUserID >>= return . ((==) 0)
import System.Posix.User
main=do
is_root>=返回。((==) 0)
哎哟!有更好的方法吗?

一种方法是

fmap (== 0) getRealUserID
(我假设您的目标是限制
uid
的范围,而不仅仅是为了它本身的目的而无点限制)

在这样一个简单的情况下,这可能是一条可行的道路。来自
控件的操作符
在这里特别有用

foo = do
  are_same <- (==) <$> doThis <*> doThat

任何长得很长的函数都应该是它自己的函数。

注意
m>>=return。根据
Monad
定律,f
(与问题中的代码一样)必须等于
fmap fm
:您也可以使用应用程序实例,例如:
is_root@PeterHall
()
仍然是
Functor
实例中
fmap
的同义词,它经常与应用程序符号一起使用(并为此目的从
Control.applicative
重新导出)。()也在Data.Functor中。当计算在
IO
上下文中运行时(通过适当的导入)
Functor
applicative
当然还有
Monad
实例确实存在,您可以随意应用任何映射函数。这并不能消除额外的变量,但您还应该使用
let is_root=uid==0
而不是
is_root我看不出您的尝试有什么不好的地方,只要在bind的正确操作数中,它可能会缩短为
return。(==0)
foo = do
  are_same <- (==) <$> doThis <*> doThat
complicatedEq :: This -> That -> IO Bool

main = do
  are_same <- do
    this <- doThis
    that <- doThatBasedOn this
    complicatedEq this that
  ... rest ...