2016-10-24 3 views
2

関数と2つの入力を受け取り、関数を最大化する引数を返す関数を記述しようとしています。この私が使用する設定です。たとえば関数による最大化

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

次のように、機能は動作するはずです:

maximize (+3) 5 10 = 10 

(3 + 5)<(3 + 10)ため

私は私はこのような何かをする必要があると考えています:

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

このアプローチはうまくいかないようです。何か助けてくれてありがとう!

+5

'maximize f x y = maximumBy(xを比較する)[x、y]' – user2407038

+5

'Eq a'制約はあなたにとって役に立たないことに注意してください。引数が等しいかどうかを確認する必要はなく、比較する必要があるのは結果だけなので、その制約を省略することもできます。しかし、あなたは関数の_result_でそれを多相にすることができます。そして、あなたはそのような制約を必要としますが、 'Eq'では十分ではありません。' Ord b =>(a - > b) a-> a-> a'となる。 – leftaroundabout

+0

ここで私たちはこの質問にお答えしますか?あなたはあなたの答えを受け取りましたか? –

答えて

7

あなたの問題はxまたはyどちらかとは対照的に、max (f x) (f y)は、f xまたはf yのいずれかをバック与えることです。以前の値のペアを比較し、後者の値の1つを返す必要があります。それを行う1つの方法は、このように、その結​​果に、パターンマッチングをcompareを使用している:あなたはcomparing f x ycompare (f x) (f y)を交換することができますData.Ordからcomparingを使用している書き込み用

-- 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.) 

つのショートカットを、。上記のuser2407038で提案されているもう1つのショートカットは、Data.ListmaximumByを使用して、すべてを1つのライナーmaximumBy (comparing f) [x,y]に減らします。

+1

''比較=(比較 'on')' '、より一般的に使用できるパターンです。 – dfeuer

5

どのように簡単な実装について:

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

いいです。これは、 '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'を使ってください。 – dfeuer

関連する問題