この質問はXY Problemのような少しを感じています。私はあなたのメッセージの中でソート関数を渡すことについて別の考え方を提供したいと思います(私はあなたのコードベースに精通していないという注意点、あなたの質問に与えた例のみ)。
タイプパラメータをMsg
に追加するのはちょっと面倒なようですが、一歩前に戻ってみましょう。ソートには、同じ型の2つをある方法で比較し、最初の値が2番目の値よりも小さいか等しいか大きいかどうかを返します。 ElmはすでにタイプコンストラクタLT、EQ、GT(Less Than、EQual、およびGreater Than)を持つものを比較するために使用するOrder
タイプを持っています。
はのは、次のようにあなたのMsg
をリファクタリングしてみましょう:
type Msg
= Sort (Product -> Product -> Order)
今、私たちはMsg
に型パラメータを追加する必要はありません。しかし、どのようにして並べ替えるのはProduct
のフィールドを指定するのですか?私たちはそれをカリングすることができます。
はのは、その最初の引数と同じタイプの他の二つの引数として関数を受け取りcomparing
と呼ばれる別の関数を定義してみましょう、とOrder
値を返す:最初の引数が関数である
comparing : (a -> comparable) -> a -> a -> Order
comparing f x y =
compare (f x) (f y)
お知らせをここに方法ですこれは、あなたの例がSort
コンストラクタの(Product -> comparable)
引数で試行しようとしたものに似ています。それは偶然ではありません。さて、カリングを使用することによって、comparing
関数を、.name
または.price
のようなレコードフィールドゲッターで部分的に適用することができます。あなたの例を修正するには、onClick
ハンドラは次のようになります。
onClick (Sort (comparing .name))
あなたはこのルートを行く場合は、より多くのリファクタリングがあるでしょう。この比較機能があるので、update
関数でどのように使用しますか?Model
にList Product
のproducts
というフィールドがあるとします。その場合は、List.sortWith
関数を使用してリストを並べ替えることができます。 comparing
機能についてこのビジネスはまっすぐ、それは同じことを満たしハスケルから来
:
case msg of
Sort comparer ->
{ model | products = List.sortWith comparer model.products } ! []
少数決算の思考やその他の注意事項:Sort
Msg
のためのあなたの更新の場合は、次のようになります必要。
上記のようにSort
コンストラクタを定義するのではなく、私はおそらくそれがそのような共通のイディオムであるため、もう少し抽象化するでしょう。
type alias Comparer a =
a -> a -> Order
type Msg
= Sort (Comparer Product)
そして、ちょうどこのすべてコネクト、
comparing
、次の2つのタイプの注釈が同一であるか説明するために、さらに一歩それを取るために:あなたはここに示されているよう
Msg
を再定義し、その後、このような一般的な機能のためのエイリアスを定義することができます:
-- this is the original example from up above
comparing : (a -> comparable) -> a -> a -> Order
-- this example substitutues the `Comparer a` alias, which may help further
-- your understanding of how it all ties together
comparing : (a -> comparable) -> Comparer a
elmコンパイラの指示に従って試しましたか? おそらく宣言を次のように変更する必要があります: 'type Msg comparable = ... ' – daniula