2

いくつかのタイプがありますRecord

type Day         = Integer
type Description = String
type Name        = String
type PhoneNumber = String
type Year        = Integer

data Month = January | February | March | April | May | June | July
           | August | September | October | November | December
           deriving (Eq, Ord, Enum, Show)
data Birthday = Birthday Month Day
  deriving (Eq, Show)
data DatingDate = DatingDate Year Month Day
  deriving (Eq, Show)

data Record = BirthdayRecord Name Birthday
            | PhoneRecord Name PhoneNumber
            | DatingRecord DatingDate Description
            deriving (Eq, Show)

そして、これらのレコードを日付でフィルタリングする関数:

getAssignment :: (Year, Month, Day) -> [Record] -> [Record]
getAssignment (year, month, day) = filter matchDate
  where matchDate (BirthdayRecord _ (Birthday month day)) = True
        matchDate (DatingRecord (DatingDate year month day) _) = True
        matchDate _ = False

エラーのため、この定義getAssignmentは正しくありません。

warning: Defined but not used: `year'

year実は、パターンが一致する部分getAssignmentyearパターンが一致する部分がmatchDate同じではないのは、私にとってはちょっと驚きです。

yearでは、変数のスコープ境界はどこで開始および終了しますか?それはセクションのために起こりwhereますか?

(year, month, day)ところで、このエラーは、変数を何度も使用することで回避できます。

getAssignment' :: (Year, Month, Day) -> [Record] -> [Record]
getAssignment' date = filter (matchDate date)
  where matchDate (_, m, d) (BirthdayRecord _ (Birthday month day)) =
          month == m && day == d
        matchDate (y, m, d) (DatingRecord (DatingDate year month day) _) =
          year == y && month == m && day == d
        matchDate _ _ = False

どうすれば書き直すことができますか?

4

2 に答える 2

4

スコープは、パターン内の変数が常に新しい変数バインディングを定義することを除いて、式全体(where句の定義を含む)です。

同じ名前を再利用する代わりに、内部バインディングで異なる変数名を使用する必要があります。

getAssignment :: (Year, Month, Day) -> [Record] -> [Record]
getAssignment (year, month, day) = filter matchDate
  where matchDate (BirthdayRecord _ (Birthday month' day'))
           = month == month' && day == day'
        matchDate (DatingRecord (DatingDate year' month' day') _)
           = year == year' && month == month' && day == day'
        matchDate _ = False

変数名を再利用して変数を外部スコープから非表示にすることをシャドウイングと呼びます。-Wallを使用する場合(または-fwarn-name-shadowingこの警告のみを有効にする場合)、GHCはこれを行うときに警告する必要があります。

編集:あなたの特定の関数については、これはおそらくそれを書くためのより明確な方法です:

getAssignment :: (Year, Month, Day) -> [Record] -> [Record]
getAssignment (year, month, day) = filter matchDate
  where matchDate (BirthdayRecord _ birthday) = birthday == Birthday month day
        matchDate (DatingRecord date _)       = date == DatingDate year month day
        matchDate _                           = False

ただし、他のパターンと比較する場合でも、パターンの一部に名前を付けることは避けられません。

于 2012-04-07T19:53:00.690 に答える
0

パターンマッチングの形式は次のとおりです。コンストラクターbinding1binding2...ここで、バインディングは、使用する値の一部に名前を付けることができます(そして唯一!)。左側で値を計算するときにできることはこれだけです。最初の例では、バインドされた名前をバインディングに含めることで一致を制限したいようですが、それはそのようには機能しません。あなたが欲しいものについては警備員を参照してください。

于 2012-04-07T20:21:09.630 に答える