質問

時々、「最後の引数を2回使用してください」という問題につまずき、例えば、ポイントフリースタイルを書くか、ラムダを避けるために。例えば

sqr x = x * x

と書くことができます

sqr = doubleArgs (*) where
   doubleArgs f x = f x x

または、このやや複雑な機能を考慮してください(から取られた この質問):

ins x xs = zipWith (\ a b -> a ++ (x:b)) (inits xs) (tails xs)

このような関数があれば、このコードポイントフリーを書くことができます。

ins x = dup (zipWith (\ a b -> a ++ (x:b))) inits tails where
     dup f f1 f2 x = f (f1 x) (f2 x)

しかし、HoogleでDoubleargsやDupのようなものを見つけることができないので、ここでトリックやイディオムを見逃すかもしれないと思います。

役に立ちましたか?

解決

から Control.Monad:

join :: (Monad m) -> m (m a) -> m a
join m = m >>= id

instance Monad ((->) r) where
    return = const
    m >>= f = \x -> f (m x) x

拡大する:

join :: (a -> a -> b) -> (a -> b)
join f = f >>= id
       = \x -> id (f x) x
       = \x -> f x x

だから、ええ、 Control.Monad.join.

ああ、そしてあなたのポイントフリーの例のために、あなたはアプリケーション表記を使用してみましたか(から Control.Applicative):

ins x = zipWith (\a b -> a ++ (x:b)) <$> inits <*> tails

(なぜ人々がとても好きなのかわかりません a ++ (x:b) それ以外の a ++ [x] ++ b...それはより速くありません - インライナーがそれを処理します - そして、後者ははるかに対称的です!しかたがない)

他のヒント

あなたが「doubleargs」と呼ぶものは、より頻繁にdupと呼ばれます - それはWコンビネーター(mockingbirdをmockto mockbird in to mockbird) - 「The Elementary Duplicator」です。

あなたが「dup」と呼ぶのは、実際には「スターリングプライム」コンビネーターです。

Haskellにはかなり小さい「コンビネーターの基礎」があります。データを参照してください。さらに、いくつかのアプリケーションおよびモナディック操作は、アプリケーションとモナドの関数インスタンスにより、より多くの「標準」組み合わせを追加します(<*>は、s-スターリングコンビネーターです。機能的インスタンス、lifta2&liftm2はスターリングプライムです)。データを拡大するためにコミュニティにはあまり熱意がないように思われます。機能しているため、コンビネーターは楽しいですが、実用的には、コンビネーターが直接利用できない状況で長い手を好むようになりました。

これが私の質問の第2部の別の解決策です:矢印!

import Control.Arrow

ins x = inits &&& tails >>> second (map (x:)) >>> uncurry (zipWith (++))

&&& ( "Fanout")引数を2つの関数に分配し、結果のペアを返します。 >>> ( "and")関数アプリケーションの順序を逆転させます。これにより、左から右に一連の操作が可能になります。 second ペアの第2部でのみ動作します。もちろん、あなたは必要です uncurry 最後に、2つの引数を期待する関数でペアを供給します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top