2

パラメータがリストと演算子を受け取る関数を定義したいと思います。これは私が現在持っているものです。最小値または最大値を見つけることができる高階関数を定義しようとしています。

largest :: (a -> a -> Bool) -> a
largest = findType (>)

findType :: (a -> a -> Bool) -> [a] -> a
findType op [] = error "empty list"
findType op [x] = x
findType op (x:xs) 
    | x op maxTail = x
    | otherwise = maxTail
    where maxTail = findType op xs

ただし、現在は機能していません。

4

3 に答える 3

3

任意のa -> a -> Bool関数パラメーターを受け入れる関数を作成するか、同等のデータ型がOrdクラスを実装するという事実を使用できます。

これは、リストがソートされているかどうかを確認するための両方の方法を示すコードです。

option1 :: (a->a->Bool) -> [a] -> Bool
option1 op (a:b:ls) = op a b && option1 op (b:ls)
option1 op _ = True

option2 :: (Ord a) => Ordering -> [a] -> Bool
option2 op (a:b:ls) = compare a b == op && option2 op (b:ls)
option2 op _ = True

main = do
   let ls = [1, 2, 3]
   print $ option1 (<) ls
   print $ option2 LT ls

2番目の方法では、値と(それぞれ<、=、>を意味する)Orderingのみを持つデータ型を使用する必要があることに注意してください。たとえば、許容値のリストやその他のデータ構造を渡すことで、より柔軟にすることができますが、ほとんどの場合、最初のオプションの方が適切です。LTEQGTOrdering

于 2013-03-09T06:20:41.673 に答える
1

GHCは、関数opをコードの演算子として使用することを知らないので、彼に伝える必要がありますが、どうすればそれを実行できますか?

elem関数について考えてみましょう。この関数は、値とリストを受け取り、値がリストに存在するかどうかに応じてTrueまたはFalseを返します。

elem :: Eq a => a -> [a] -> Bool
elem 2 [1,2,3] => True

基本的には関数として見られますが、本当に便利な演算子として使用したい場合は、`で囲む必要があります。

2 `elem` [1,2,3] => True

findTypeの呼び出しに関するdidiercのコメントをwhere句に追加すると、機能するコードが得られます。

とにかく、再帰呼び出しをガードに入れるのは非常に悪い考えです。コードは最も読みにくく、パフォーマンスの問題につながる可能性があるかどうかはわかりません。アキュムレータの使い方を学ぶ必要があります、これを見てください



逆に、関数がデフォルトで演算子と見なされる場合、関数として使用するには、関数を()で囲みます。

2 : [] => [2]

(:) 2 [] => [2]
于 2013-03-09T10:05:38.850 に答える
1

2 つの異なる問題としてのコード。最初にコンパイラ エラーを生成するものに対処しましょう。

あなたはfindType次の署名に署名しました:

findType :: (a -> a -> Bool) -> [a] -> a

意図は、2 番目のパラメーターとして指定されたリストから、最初のパラメーターとして指定された順序付け述語によって指示される境界を抽出することです。

ただし、まさに関数定義の最後の行で 、述語を省略した式にfindTypeバインドします。maxTailfindType xs

もちろん、正しい行は次のとおりです。

where maxTail = findType op xs

あなたの 2 番目のエラーはlargest関数の署名に関連していますが、それが何であるかを正確に知ることができます。

于 2013-03-09T08:12:36.543 に答える