Haskell:检查所有条件是否都为真。如果他们返回true,否则为假

时间:2013-09-10 22:28:03

标签: haskell if-statement boolean multiple-conditions

我今天下午写了一些Haskell,我有一份必须满足的条件清单。如果它们都是真的我想要返回true,如果其中一个是假的,那么返回false。

我有一种方法可行,但我只是想知道是否有更好的方法来实现它的可读性/效率。

这就是我所拥有的:

checkMatch :: Person -> Person -> Bool
checkMatch seeker candidate
    |  gender candidate == preferedGender seeker 
    && gender seeker == preferedGender candidate
    && minAcceptableAge seeker <= age candidate 
    && maxAcceptableAge seeker >= age candidate
    && minAcceptableAge candidate <= age seeker
    && maxAcceptableAge candidate >= age seeker = True
    |  otherwise = False

性别定义为:

data Gender = Male | Female (Eq)

所以我只是调整了&amp;&amp;和s'以使它看起来更好一点,但我觉得必须有更好的方法,但似乎无法想出任何搜索谷歌的东西。< / p>

先谢谢!

6 个答案:

答案 0 :(得分:7)

您可以丢失警卫并使用and检查您的情况:

checkMatch :: Person -> Person -> Bool
checkMatch seeker candidate = and [ 
    gender candidate           == preferedGender seeker 
  , gender seeker              == preferedGender candidate
  , minAcceptableAge seeker    <= age candidate 
  , maxAcceptableAge seeker    >= age candidate
  , minAcceptableAge candidate <= age seeker
  , maxAcceptableAge candidate >= age seeker
  ]

答案 1 :(得分:2)

你可以滥用may monad的语法糖作为:

a |==| b = guard $ a == b
a |>=| b = guard $ a >= b
a |<=| b = guard $ a <= b
a |/=| b = guard $ a /= b

checkMatch :: Person -> Person -> Bool
checkMatch seeker candidate = Just () == do
  gender candidate |==| preferedGender seeker
  gender seeker |==| preferedGender candidate
  minAcceptableAge seeker |<=| age candidate 
  maxAcceptableAge seeker |>=| age candidate
  minAcceptableAge candidate |<=| age seeker
  maxAcceptableAge candidate |>=| age seeker

答案 2 :(得分:1)

嗯,首先,您可以and轻松,保护条件。

接下来,我应该将minAccAge <= age && maxAccAge >= age模式重构为专用函数,比如说

acceptsAge :: Person -> Age -> Bool
judge `acceptsAge` age
   = age >= minAcceptableAge judge && age <= maxAcceptableAge judge

它仍然是

checkMatch :: Person -> Person -> Bool
checkMatch seeker candidate
  | gender candidate == preferedGender seeker 
  , gender seeker == preferedGender candidate
  , seeker `acceptsAge` age candidate 
  , candidate `acceptsAge` age seeker         = True

我将其留在此处,两个preferedGender检查不能减少太多。

答案 3 :(得分:1)

你问的是风格问题,所以没有正确或错误的答案。但是,这里有一些建议。

首先,您正在编写此模式的等效内容:

isTrue value | value == True = True
             | otherwise     = False

当然可以简化为:

isTrue value = value

其次,当您检查 all 所需的多个测试时,您可以使用and函数并将测试作为列表元素传递。如果所有元素都为True,则会返回True,否则会短路并返回False

将这两个想法放在一起我们得到:

checkMatch :: Person -> Person -> Bool
checkMatch seeker candidate
  = and [gender candidate == preferedGender seeker, 
         gender seeker == preferedGender candidate,
         minAcceptableAge seeker <= age candidate,
         maxAcceptableAge seeker >= age candidate,
         minAcceptableAge candidate <= age seeker,
         maxAcceptableAge candidate >= age seeker]

......这可能就是我写它的方式。

答案 4 :(得分:1)

我注意到您的代码包含一些重复内容,因为您会检查两个方向上的内容。我将定义一个辅助函数checkAcceptable,它只检查一个方向,而不是两次调用该函数:

checkAcceptable :: Person -> Person -> Bool
checkAcceptable seeker candidate =
  gender candidate == preferedGender seeker &&
  minAcceptableAge seeker <= age candidate &&
  maxAccetableAge seeker >= age candidate

checkMatch :: Person -> Person -> Bool
checkMatch seeker candidate =
  checkAcceptable seeker candidate &&
  checkAcceptable candidate seeker

答案 5 :(得分:1)

对于代码最小化,您可以像这样编写

inRange x (a,b) = a <= x && x <= b

checkOneWay a b = gender b == preferredGender a
               && age b `inRange` (minAcceptableAge a, maxAcceptableAge a)

checkMatch candidate seeker = checkOneWay candidate seeker
                           && checkOneWay seeker candidate