2016-10-24 2 views
2

Я пытаюсь написать функцию, которая принимает функцию и два входа, и возвращает аргумент, который максимизирует функцию. Это настройки я хочу использовать:Максимизация по функции

max :: Eq a => (a -> Int) -> a -> a -> a 

Например, функция должна работать следующим образом:

maximize (+3) 5 10 = 10 

Потому что (3 + 5) < (3 + 10)

I я думаю, что мне нужно сделать что-то вроде этого:

maximize :: Eq a => (a -> Int) -> a -> a -> a 
maximize f x y = max (f x) (f y) 

Этот подход, похоже, не работает. Спасибо за любую помощь!

+5

'maximize f x y = maximumBy (сравнение f) [x, y]' – user2407038

+5

Обратите внимание, что ограничение 'Eq a' не делает ничего полезного для вас. Вам не нужно проверять, равны ли аргументы, все, что вам нужно сравнить, это результаты, поэтому вы можете также опустить это ограничение. Тем не менее, вы можете сделать это также полиморфным в функции _result_, и тогда вам понадобится такое ограничение - но 'Eq' недостаточно, вам понадобится' Ord b => (a -> b) -> a -> a -> a'. – leftaroundabout

+0

Где мы находимся по этому вопросу? вы получили ответ? –

ответ

7

Ваша проблема заключается в том, что max (f x) (f y) возвращает либо f x или f y, в отличие от любой x или y. Вы должны сравнить прежнюю пару значений и затем вернуть один из последних. Один из способов сделать это является использование compare, а затем сопоставления с образцом на его результат, например:

-- You don't actually need the `Eq a` constraint here. 
maximize :: (a -> Int) -> a -> a -> a 
maximize f x y = case compare (f x) (f y) of 
    -- etc. (I will let you fill in the details.) 

один ярлык для записи, который использует comparing из Data.Ord, что позволяет заменить compare (f x) (f y) с comparing f x y. Дальнейший ярлык, предложенный выше пользователем2407038, использует maximumBy от Data.List, чтобы уменьшить его до однострочного maximumBy (comparing f) [x,y].

+1

'' compareing = (compare 'on')' ', шаблон, который можно использовать гораздо более широко. – dfeuer

5

Как о прямой реализации:

maximize f x y = if (f x) > (f y) then x else y 
+2

Ницца. Это, конечно, точно эквивалентно решению 'compare', учитывая, что' (>) 'может быть выражено в терминах анализа случая результата' compare', а if-then-else - это просто синтаксический сахар над анализ ситуации на «Bool» - и тем не менее этот способ написания может выглядеть немного более интуитивным для абсолютного новичка.То, что никто еще не упомянул об этом событии, пока еще не показывает, сколько инстинктивного уклонения против if-then-else существует здесь :) – duplode

1

Другой вариант

maximize f x y = argmax f [x,y] 

, но это требует установки list-extras package.

Однако, я думаю, что другие ответы более идиоматичны (@duplode) и более простые (@Uri Goren).

0

разные, но очень простой, подход с использованием стражники:

maxiM :: (Ord b) => (a -> b) -> a -> a -> a 
maxiM func v1 v2 
    | (func v1) < (func v2)  = (func v2) 
    | otherwise     = (func v1) 

Я предлагаю смотреть на learnyouahaskell.

+0

Ограничение 'Ord a 'является избыточным. Используйте 'Ord b' и' a -> b', как предлагает leftaroundabout. – dfeuer

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