Haskellで自由なスタイルをカリー化とポイントについての混乱
質問
私は機能を実装しようとしていた。
every :: (a -> IO Bool) -> [a] -> IO Bool
<のhref = "https://stackoverflow.com/questions/160170/language-showdown-lazy-aka-short-circuit-evaluation-for-and-and-or-applied-toのためのトピックがありました「>この質問を。私はこれをを明示的な再帰なしを実行しようとしました。私は次のコードを思いついた。
every f xs = liftM (all id) $ sequence $ map f xs
それは怠惰ではなかったので、私の関数は(質問で必要とされたもの)は動作しませんでしたので、そこにはupvotes: - 。)
しかし、私はそこに停止しませんでした。私はそれが短い(そしておそらくクーラー)になるように、機能のポイントフリーを作ってみました。
:引数f
とxs
は、私はちょうどそれらをドロップ式の最後のものであるため、
every = liftM (all id) $ sequence $ map
しかし、予想通り、これは動作しませんでした、実際にはそれが全く動作しませんでした。
[1 of 1] Compiling Main ( stk.hs, interpreted ) stk.hs:53:42: Couldn't match expected type `[m a]' against inferred type `(a1 -> b) -> [a1] -> [b]' In the second argument of `($)', namely `map' In the second argument of `($)', namely `sequence $ map' In the expression: liftM (all id) $ sequence $ map Failed, modules loaded: none.
それはなぜですか?私は単に基本的にカリー化とは何かである関数の引数を、末尾にドロップすることが可能であったという印象の下にありました。
解決
$の定義がある。
f $ x = f x
のは、完全にあなたの関数を括弧してみましょう。
every f xs = (liftM (all id)) (sequence ((map f) xs))
とあなたのカリーバージョン:
every = (liftM (all id)) (sequence map)
あなたが気づいたように、これらは同一ではありません。あなたは、彼らだけが適用される最後のものである場合に、関数の引数を末尾にドロップすることができます。たとえば、
f x = g c x
実際にある
f x = (g c) x
とxに(グラムC)の適用は、最後に来て、あなたが書くことができますので、
f = g c
アプリケーションオペレータ$の一つのパターンは、それは多くの場合、組成演算子になることです。ポイントフリー版インチこれは、
でありますf $ g $ x
タグに相当します
(f . g) $ x
たとえば、
every f xs = liftM (all id) $ sequence $ map f xs
タグになることができます
every f xs = (liftM (all id) . sequence . map f) xs
あなたは、xsをドロップすることができ、その時点でます:
every f = liftM (all id) . sequence . map f
引数Fをなくすそれは合成作用素の前に適用されるため、より困難です。さんが http://www.haskell.org/haskellwiki/Pointfreeするからドットの定義を使用してみましょう:
dot = ((.) . (.))
の点で、これは
(f `dot` g) x = f . g x
私たちは、すべてが完全にポイントのないようにする必要があり、まさに次のとおりです。
every = (liftM (all id) . sequence) `dot` map
悲しいことに、Haskellの型システムにおける制限のため、これは明示的な型シグネチャを必要とします:
every :: (Monad m) => (a -> m Bool) -> [a] -> m Bool