13

私は昨日 haskell から始めましたが、この素晴らしい新世界の岸辺でまだ完全に迷子になっています。今、私は次の問題に遭遇しました:

整数と別の変数に魔法をかける関数があるとしましょう。

makeTuple :: Int -> a -> (Int, a)
makeTuple n x = (n, x)

ここで、この関数をリストのすべての要素に適用したいと思います。これまでのところ、問題はありません。マッピングは、Python (私の出身地) での毎日のパンとバターでもあるからです。

makeTupleList :: Int -> [a] -> [ (Int, a) ]
makeTupleList n x = map (makeTuple n) x

私が理解している限り、バイナリ関数 makeTuple は整数 n で部分的に適用されるため、x の各要素にマップできる単項関数になります。これまでのところ、すべて順調です。

しかし、makeTuple 関数に次のような別の署名がある場合はどうすればよいでしょうか。

makeTuple2 :: a -> Int -> (Int, a)
makeTuple2 x n = (n, x)

ローマに通じる道はたくさんあります。結果は同じですが、道は異なります。明らかに、マッピングはもう機能しません。関数は Int を期待し、a を取得します。

makeTupleList2 :: Int -> [a] -> [ (Int, a) ]
makeTupleList2 n x = map (makeTuple2 n) x -- boolshit

これは当然のことでした。私の - おそらく Pythonic すぎる - 回避策は、別の関数を使用して、パラメーターをどこに渡すかです。

makeTupleList2 :: Int -> [a] -> [ (Int, a) ]
makeTupleList2 n x = map (\x -> makeTuple2 x n) x

質問: 部分的に適用されたパラメーターが一番左にない場合に関数を部分的に適用する、関数型の Haskell スタイルの好ましい方法は何ですか?

4

4 に答える 4

16

flip関数の 1 番目と 2 番目の引数を交換するを使用できます。

makeTupleList2 n x = map (flip makeTuple2 n) x

別のオプションは、バッククォート構文を使用して中置演算子を作成し、演算子セクションを使用して部分的に適用することです。

maleTupleList2 n x = map (`makeTuple2` n) x

または、あなたが言ったように、ラムダ式を使用できます。どちらを使用するかは、コンテキストと個人の好みによって異なります。最も明確に感じられるものを使用してください。


PS:あなたがしていることは、部分適用と呼ばれます。(a, b) -> cカリー化とは、複数の引数を取る関数をカリー化された形式 a -> b -> cに変換して、部分的に適用できるようにするプロセスです。

于 2011-07-16T14:35:09.113 に答える
1

関数がタプルコンストラクターのみの場合:

makeTuple x y = (x,y)

(これは次のように書くこともできますmakeTuple = (,))次に、これには特別な拡張機能があります。

{-# LANGUAGE TupleSections #-}
makeTupleList2 n x = map (n,) x
makeTupleList2' n x = map (,n) x     -- Use n as the second component

これは次のように書くこともできます

makeTupleList2 n = map (n,)
makeTupleList2' n = map (,n)

それ以外の場合は、すでに提案されている方法を使用してください。

于 2011-07-16T14:49:59.070 に答える
1

Prelude は次のように定義されているため、 に\x -> makeTuple2 x n置き換えることができます: (私の実装であり、彼らのものではありません)flip makeTuple2 nflip

flip :: (a -> b -> c) -> b -> a -> c
flip f y x = f x y

したがって、

makeTupleList2' = map . flip makeTuple2

または、それが単なるタプルであることを見てください:

makeTupleList2'' = map . (,)

また、zipを使用できることに注意してください(これがどれほど効率的かはわかりません):

makeTupleList2''' :: a -> [b] -> [(a, b)]
makeTupleList2''' = zip . repeat
于 2011-07-16T14:33:43.537 に答える
1

この特定のケースでは、 を使用できますがflip makeTuple2 n、それは 2 つの引数を持つ関数に対してのみ機能します。しかし、一般的に、ラムダがハスケリーではない、またはPythonicすぎるという解決策は見つかりません。

于 2011-07-16T14:35:36.990 に答える