如何避免Haskell中的重复函数调用

时间:2014-11-19 19:24:59

标签: haskell

如何避免此Haskell命令中的重复x

ccheck :: Balance -> Integer
ccheck b     | x >= 1200    = x - 7
             | otherwise    = x
               where x = account b

6 个答案:

答案 0 :(得分:6)

嗯,你可以做任何无点的事情。

import Control.Arrow
ccheck = uncurry (+) . (min 0 . (*7) . signum . (1199-) &&& id) . account

但是WTH。你的版本很好,它正在发生的事情更加清晰,正如上校三十二所说的那样,它根本不是重复的。

答案 1 :(得分:2)

如果您愿意,可以完全省略:

ccheck = ((+) <*> ((-7) *) . signum  . (1+) . signum . (-1200 +)) . account

然而,这并不比条件情况更具可读性(特别是,为了避免使用if语句我们正在使用signum . (1+) . signum,这有点令人头疼;最右边的一个映射低于集合{-1,0,1}的整数和(1+)将其转换为{0,1,2},下一个signum再次减少为{0,1}。

答案 2 :(得分:2)

你可以使它的可读性低得多

ccheck = join (liftM2 if' (>= 1200) (subtract 7)) . account
    where if' b l r = if b then l else r

答案 3 :(得分:2)

“改善”@bheklilr的答案:

import Control.Monad
import Data.Bool
ccheck = liftM3 bool id (subtract 7) (>= 1200) . account

另一个“无意义”风格的例子。

答案 4 :(得分:1)

我不认为代码是重复的,但不过这是我的看法。首先,介绍以下组合器:

cond p f g x = if p x then f x else g x

然后,将ccheck定义为:

ccheck = cond (>= 1200) (subtract 7) id . account

答案 5 :(得分:0)

如果您想进行更多检查,请从头顶开始:

ccheck = chainConditions [((>=1200), subtract 7] id . account

chainConditions :: [(a -> Bool, a -> b)] -> (a -> b) -> a -> b
chainConditions [] g x = g x
chainConditions ((p,f):rest) g x = 
    | p x = f x
    | otherwise = chainConditions rest g x

使用@Xavier Pinho的答案,这可能也可以表达为foldr (.) otherwiseFunction (map (uncurry cond) conditions),但这是一个疯狂的猜测!你可以把DRY推得太远; - )