私はここ数週間Haskellを勉強しています(ただの楽しみのため)そしてブライアン・ベックマンの素晴らしいモナドを紹介するビデオ彼は、より一般的な合成演算子を作成する必要性からモナドを動機付けています。この考え方に従うと、2 つの関数があるとします。
f :: a -> b
g :: b -> c
合成演算子は、
h = g . f :: a -> c
そして、これから.
演算子の正しい型を推測することができます。
(.) : (b -> c) -> (a -> b) -> (a -> c)
モナドに関しては、次の 2 つの関数があるとします。
f :: a -> m b
g :: b -> m c
自然な選択としては、次のように動作する一般化された合成演算子を定義することだったと思われます。
h = f >>= g :: a -> m c
この場合、>>=
演算子の型シグネチャは次のようになります。
(>>=) :: (a -> m b) -> (b -> m c) -> (a -> m c)
しかし実際には、演算子は次のように定義されているようです。
h a = (f a) >>= g :: m c
したがって
(>>=) : m b -> (b -> m c) -> m c
誰か、bind の定義をこのように選択した理由を説明してくれませんか? 2 つの選択肢の間には、一方を他方の観点から表現できる単純なつながりがあると思いますが、現時点ではわかりません。
ベストアンサー1
誰か、bind の定義をこのように選択した理由を説明してくれませんか?
確かに、それはあなたとほぼ同じ理由です。ただ...私たちはもっと一般的なものを欲しかったのです応用演算子であり、より一般的な合成演算子ではありません。ポイントフリー プログラミングを多く (または少しでも) 行ったことがあるなら、その理由はすぐにわかるでしょう。ポイントフリー プログラムは、ポイントフル プログラムに比べて書きにくく、読みにくいからです。たとえば、次のようになります。
h x y = f (g x y)
関数適用では、これは完全に簡単です。関数合成のみを使用するバージョンはどのようになりますか?
h = (f .) . g
これを初めて見たときに、1、2 分ほど立ち止まって見つめる必要がない場合は、あなたは実際にコンピューターである可能性があります。
それで、理由は何であれ、私たちの脳は、名前と関数の適用をそのまま使うと少しだけうまく機能するようにできています。それで、あなたの議論の残りの部分は、合成の代わりに適用を使った場合、次のようになります。関数と引数がある場合:
f :: a -> b
x :: a
アプリケーションオペレータは、
h = x & f :: b
そして、これから&
演算子の正しい型を推測することができます。
(&) :: a -> (a -> b) -> b
モナドに関しては、関数と引数がモナドであると仮定します。
f :: a -> m b
x :: m a
自然な選択は、次のように動作する一般化されたアプリケーション演算子を定義することです。
h = x >>= f :: m b
この場合、>>=
演算子の型シグネチャは次のようになります。
(>>=) :: m a -> (a -> m b) -> m b