3

今日の午後、Haskell を書いていて、満たさなければならない条件のリストがあります。それらがすべて true の場合は true を返し、そのうちの 1 つが false の場合は 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)

だから私は && と | を並べて見栄えを良くしましたが、もっと良い方法が必要だと感じていますが、Google を検索しても何も思いつかないようです。

ありがとうございます!

4

6 に答える 6

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
  ]
于 2013-09-10T22:35:57.860 に答える
2

Maybe モナドを構文糖衣として悪用することができます:

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
于 2013-09-10T22:51:56.120 に答える
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
于 2013-09-11T08:24:26.870 に答える
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

このままにしておきます。2 つのpreferedGenderチェックを大幅に削減することはできません。

于 2013-09-10T22:42:43.047 に答える
1

あなたが求めているのはスタイルの問題なので、正しい答えも間違った答えもありません。ただし、いくつかの提案があります。

まず、このパターンに相当するものを書いています:

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

もちろん、これは次のように単純化できます。

isTrue value = value

第二に、すべて真である必要がある複数のテストをチェックしているので、and関数を利用してリストの要素としてテストを渡すことができます。これはTrue、すべての要素がTrueである場合に戻ります。それ以外の場合は、短絡して を返しFalseます。

これら 2 つのアイデアを組み合わせると、次のようになります。

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]

・・・たぶん、こう書くと思います。

于 2013-09-10T22:43:06.967 に答える