8

少し前に$について質問したところ、役に立つ答えが返ってきました。実際、使い方は理解できたと思いました。

私は間違っていたようです:(

この例は、チュートリアルに表示されます。

instance Monad [] where
   xs >>= f = concat . map f $ xs

なぜ$がそこで使われたのか、私には一生分からない。ghciも私を助けていません。私が行ったテストでさえ、単に$を省略したバージョンと同等であることが示されているようです。誰かが私のためにこれを明確にすることができますか?

4

3 に答える 3

11

$通常の関数適用よりも優先順位が低いため、ここで使用されます。このコードを記述する別の方法は次のようになります。

instance Monad [] where
   xs >>= f = (concat . map f) xs

ここでの考え方は、最初に関数を作成し ( concat . map f)、それをその引数に適用する ( xs) というものです。示されているように、これは単に最初の部分を括弧で囲むことによっても実行できます。

$元の定義で theを省略することはできないことに注意してください。型エラーが発生します。これは、関数合成演算子 (the .) が通常の関数適用よりも優先順位が低く、式を効果的に次のように変換するためです。

instance Monad [] where
  xs >>= f = concat . (map f xs)

関数合成演算子の 2 番目の引数はまったく関数ではないため、これは意味がありません。ただし、次の定義は理にかなっています。

instance Monad [] where
  xs >>= f = concat (map f xs)

ちなみに、これは私が好む定義でもあります。

于 2009-01-11T21:08:17.343 に答える
3

私見がなぜこれがそこで使用されているスタイルではないのかを説明したいと思います:

instance Monad [] where
  xs >>= f = concat (map f xs)

concat . map fは、いわゆるポイントフリー スタイルの記述の一例です。ここで、pointfree は「アプリケーションのポイントなし」を意味します。数学では、式で、が点に適用されるy=f(x)と言うことを思い出してください。ほとんどの場合、実際には次のように置き換えて最終ステップを実行できます。fx

f x = something $ x

f = something

のようf = concat . map fに、これは実際にはポイントフリー スタイルです。どちらがより明確かは議論の余地がありますが、無意味なスタイルは別の視点を提供することも有用であるため、正確に必要とされていない場合でも使用されることがあります。

編集: 感謝すべき Alasdair のコメントの後、pointless を pointfree に置き換え、いくつかの例を修正しました。

于 2009-01-11T22:43:27.057 に答える
1

ここで $ が使用されている理由は、(.) の型シグネチャに対するものです。

(.) :: (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 でなければなりません

于 2009-01-22T10:46:20.547 に答える