Итак, если я правильно понимаю, вам нужно сохранить несколько баллов (для разных вещей) в одном кандидате, а затем выполнить вычисления по этим баллам.
В этом случае я бы рассмотрел вопрос о том, чтобы сделать Score
отдельным типом, который будет использоваться кандидатом - тогда вы можете легко добавить несколько баллов.Если вам нужно выставить счет и проценты как прямые свойства кандидата и уведомить, используя IPropertyChange
, тогда вы сможете написать что-то вроде этого:
/// Takes a name of this score item (e.g. XXX) and a
/// function to trigger the property changed event
type Score(name:string, triggerChanged) =
let mutable score = 0
let mutable percent = 0.0
member x.Score
with get() = score
and set(v) =
score <- v
triggerChanged("Score" + name)
member x.Percent
with get() = percent
and set(v) =
percent <- v
triggerChanged("Percent" + name)
Теперь вы можете просто использовать объект Score
столько раз, сколько вам нужно в кандидате (потому что мы также хотим предоставить прямые свойства, есть некоторый шаблон, но это должно быть разумное количество):
type ScorableCandidate() as this =
// Create trigger function & pass it to Score objects
let trigger n = propertyChanged.Trigger(this, n)
let infoXxx = new Score("Xxx", trigger)
member this.InfoXxx = scoreXxx // Exposes the whole Score object
member this.ScoreXxx = scoreXxx.Score // & individual...
member this.PercentXxx = scoreXxx.Percent // ...properties
Теперь ваша параметризованная функция может просто взять функциюкоторый принимает ScorableCandidate
и возвращает объект Score
:
let scores f =
let totalScore = List.fold (fun acc (candidate: ScorableCandidate) ->
let so = f candidate // Get 'Score' object
acc + so.Score) 0 brokers
let score (candidate: ScorableCandidate) =
let so = f candidate // Get 'Score' object
so.Percent <- (float so.Score) / float totalScore * 100.0
if totalScore > 0 then
List.iter score <| brokers
Пример вызова будет простым:
scores (fun (c:ScorableCandidate) -> c.InfoXxx)
Это делает вызов функции scores
таким простым, какон может получить, и это также масштабируемое решение, которое позволяет легко добавлять другие вычисления к объекту Score
.Недостаток (например, по сравнению с простым решением Павла) состоит в том, что есть немного больше работы по проектированию типа Score
(однако объявление новых баллов в ScorableCandidate
тогда, вероятно, проще, если вам нужно только выставить читаемое свойство непосредственно вкласс - который, я думаю, должно быть достаточно).