Owe*_*wen 11 haskell coding-style
当我使用命令式语言时,我经常编写代码
foo (x) {
if (x < 0) return True;
y = getForX(x);
if (y < 0) return True;
return x < y;
}
Run Code Online (Sandbox Code Playgroud)
也就是说,我逐个检查条件,尽快打破障碍.
我喜欢这个,因为它使代码保持"平坦"并遵循"最终重量"的原则.我认为它更具可读性.
但在哈斯克尔,我会把它写成
foo x = do
if x < 0
then return x
else do
y <- getForX x
if y < 0
then return True
else return $ x < y
Run Code Online (Sandbox Code Playgroud)
我不喜欢哪个.我可以使用一个允许爆发的monad,但是因为我已经使用了monad,所以我必须使用lift所有内容,如果可以的话,我会想要避免添加单词.
我想这并不是一个完美的解决方案,但有人有任何建议吗?
fuz*_*fuz 13
针对您的具体问题:悬空do符号和逻辑用法如何?
foo x = do
if x < 0 then return x else do
y <- getForX x
return $ y < 0 || x < y
Run Code Online (Sandbox Code Playgroud)
结合hammar所说,你甚至可以得到更漂亮的代码:
foo x | x < 0 = return x
| otherwise = do y <- getForX x
return $ y < 0 || x < y
Run Code Online (Sandbox Code Playgroud)
ham*_*mar 12
使用模式和警卫可以提供很多帮助:
foo x | x < 0 = return x
foo x = do
y <- getForX x
if y < 0
then return True
else return $ x < y
Run Code Online (Sandbox Code Playgroud)
您还可以在where子句中引入小辅助函数.这往往有助于提高可读性.
foo x | x < 0 = return x
foo x = do
y <- getForX x
return $ bar y
where
bar y | y < 0 = True
| otherwise = x < y
Run Code Online (Sandbox Code Playgroud)
(或者,如果代码真的像这个例子一样简单,请使用FUZxxl建议的逻辑).
执行此操作的最佳方法是使用警卫,但是您需要先获取y值才能在警卫中使用它.这需要从getForX可能隐藏到某些monad中获得,除非通过getForX(例如IOmonad),否则你无法获得价值,然后你必须解除使用守卫进入该monad的纯函数.一种方法是使用liftM.
foo x = liftM go (getForX x)
where
go y | x < 0 = True
| y < 0 = True
| otherwise = x < y
Run Code Online (Sandbox Code Playgroud)