2013-12-01 3 views
-2

Может ли кто-нибудь объяснить мне, почему эта функция работает. Я знаю, как работает фильтр, он использует предикатную функцию и список. В этом def maximaBy valueFcn xs = filter isMaxVal xs Фильтр принимает isMaxVal как предикат, а xs - это список. , но я у меня возникают проблемы с пониманиемТребуется функция Haskell

where 
      isMaxVal xs = valueFcn xs == maxVal 
Here isMaxVal is defined as a function that takes xs as an argument but how is that possible xs is an agrument of filter. 
if we change valueFcn to function length 
we get 
isMaxVal xs = length xs == maxVal 
if xs is ["cs", "efd", "lth", "it"] length of this is 4 but maxVal ==3 
maxVal = maximum (map length ["cs", "efd", "lth", "it"]) ==3 




-- maximaBy length ["cs", "efd", "lth", "it"] == ["efd", "lth"] 
    maximaBy :: Ord b => (a -> b) -> [a] -> [a] 
    maximaBy valueFcn xs = filter isMaxVal xs 
     where 
      isMaxVal xs = valueFcn xs == maxVal 
      maxVal = maximum (map valueFcn xs) 
+1

Для записи есть уже готовая функция ['MaximumBy'] (http://hackage.haskell.org/package/base-4.6.0.1/docs/Data-List.html#v:maximumBy) , –

ответ

1

Фильтр определяется понятием, что filter p (x:xs) = x : (filter p xs)тогда и только тогда, когдаp x == True. Поэтому он фильтрует входной список, содержащий только элементы, которые удовлетворяют предикату p.

В этом случае мы определим предикат быть True только тогда, когда его значение вычисленной по входу valueFcn :: Ord b => (a -> b) равно maxVal :: b, независимо от maxVal есть.

На следующей строке, мы имеем определение maxVal чтобы быть maximum из списка ввода измененного покомпонентно («отображены») по valueFcn.

Так что в каждом случае мы просматриваем значение ввода «через» valueFcn, которое производит какое-то значение Ord b => b, которое мы можем сравнить. Мы ищем максимум и называем это «значение» (типа b) maxVal, а затем мы фильтруем список входных данных, чтобы содержать только те входы, которые соответствуют maxVal, с тем, что вычисляет valueFcn.


Чтобы быть более четким, вот еще один способ подойти к проблеме. Мы хотим, чтобы оценить каждый вход на выходе из valueFcn, поэтому мы сложите эти значения. Учитывая valueFcn :: Ord b => a -> b мы пишем

let pairs = map (\x -> (x, valueFcn x)) :: Ord b => [a] -> [(a, b)] 

И затем мы переходим сразу по списку ищет максимальное значение второго компонента каждого кортеж.

let (maxInput, maxValue) = maximumBy (\a b -> compare (snd a) (snd b)) pairs 

Это максимальный входной и его соответствующее значение, но мы еще не сделали, потому что мы считаем, что это значение может происходить несколько раз в списке ввода, поэтому мы ищем по списку снова ищет что-нибудь, что соответствует что значение

let results :: Ord b => [(a, b)] 
    results = filter (\x -> snd x == maxValue) pairs 

, а затем мы возвращаем только те входы, которые нечестные это далеко не их valueFcn значения.

map fst results 

Этот метод является на самом деле немного clunkier, чем одна ваша функция использует, но он выделяет несколько иным образом, как входные значения и их valueFcn значения связаны между собой.

+0

Да, но почему я не могу писать, как это maximaBy :: Ord Ь => (а -> б) -> [а] -> [а] maximaBy valueFcn хз = фильтр isMaxVal хз где isMaxVal хз = valueFcn xs == (максимум (map valueFcn xs)) По-прежнему не понимаю isMaxVal xs = valueFcn xs valueFcn xs = length xs (если valueFcn - длина), но это не то же самое, что и maxVal. isMaxVal xs Означает ли это, что список xs является поправкой isMaxVal? если да, то какой фильтр получает в качестве аргумента? – user2975699

+0

"мы фильтруем список входных данных, чтобы содержать только те входы, которые соответствуют maxVal, с любым значением, которое вычисляет Fcn для них". Но мы вызываем valueFcn xs? мы не вызываем valueFcn для элемента xs. – user2975699

+0

Я понимаю это сейчас. проблема была xs в IsMaxVal, я думал, что это то же самое xs, что и выше – user2975699

Смежные вопросы