関数の適用:なぜここで$が使用されるのですか?
質問
しばらく前に、 $についての質問、そして有用な答えを得ました。実際、私はそれをどのように使うか理解できたと思いました。
私は間違っていたようです:(
この例はチュートリアルに表示されます:
instance Monad [] where
xs >>= f = concat . map f $ xs
ここで$が使用された理由を私は一生知ることができません。私がそこで行ったテストでさえ、単に$を省略したバージョンと同等であることを示しているように、ghciも私を助けていません。誰かが私のためにこれを明確にすることはできますか?
解決
$
は、通常の関数アプリケーションよりも優先順位が低いため、ここで使用されます。
このコードを記述する別の方法は次のとおりです。
instance Monad [] where
xs >>= f = (concat . map f) xs
ここでの考え方は、最初に関数( concat。map f
)を構築し、それを引数( xs
)に適用することです。示されているように、これは、最初の部分を括弧で囲むことによっても実行できます。
元の定義で $
を省略することはできません。型エラーが発生することに注意してください。これは、関数合成演算子(。
)の優先順位が通常の関数アプリケーションよりも低く、式を効果的に変換するためです。
instance Monad [] where
xs >>= f = concat . (map f xs)
これは意味がありません。関数合成演算子の2番目の引数が関数ではないためです。次の定義は理にかなっていますが:
instance Monad [] where
xs >>= f = concat (map f xs)
ちなみに、これは私が好む定義でもあります。なぜなら、私にはもっと明確に思えるからです。
他のヒント
私がこれがそこで使われているスタイルではない理由を説明したいと思います:
instance Monad [] where
xs >>= f = concat (map f xs)
concat map f
は、いわゆるポイントフリースタイルの書き込みの例です。ここで、ポイントフリーとは、「適用ポイントなし」を意味します。数学では、式 y = f(x)
で、 f
がポイント x
に適用されることを思い出してください。ほとんどの場合、実際に最終ステップを実行して、次のものを置き換えることができます。
f x = something $ x
with
f = something
like f = concat。 map f
、これは実際にはポイントフリースタイルです。
どちらが明確であるかは議論の余地がありますが、ポイントフリースタイルは異なる視点を提供し、これもまた有用であるため、正確に必要でない場合でも使用されることがあります。
編集:Alasdairのコメントの後に、無意味なものをpointfreeに置き換え、いくつかの例を修正しました。ありがとうございます。
ここで$が使用されている理由は、(。)の型シグネチャに対するものです:
(.) :: (b -> c) -> (a -> c) -> a -> c
こちら
map f :: [a] -> [[b]]
および
concat :: [[b]] -> [b]
したがって、最終的に
concat . map f :: [a] -> [b]
および(。)のタイプは次のように記述できます
(。)::([[b]]-> [b])-> ([a]-> [[b]])-> [a]-> [b]
concatを使用する場合。 map f xs
、それが表示されます
map f xs :: [[b]]
したがって、(。)とともに使用することはできません。 (タイプは(。)::(a-> b)-> a-> b
でなければなりません