写真のファンクター、適用ファンクター、モナド

簡単な意味は次のとおりです。


そして、関数を適用する方法を知っています。


小学校。 それでは、タスクを複雑にしてみましょう-コンテキストが重要です。 今のところ、コンテキストは単に値を入力できるボックスと考えることができます。


これで、この値に関数を適用すると、コンテキストに応じて異なる結果が得られます 。 これは、ファンクター、適用ファンクター、モナド、矢印などが基づいている主要なアイデアです。 Maybeデータ型は2つの関連するコンテキストを定義します:


 data Maybe a = Nothing | Just a 

後で、 Just a vs Nothing関数の動作の違いを確認します。 しかし、最初にファンクターについて話しましょう!

ファンクター


コンテキストに値がパックされている場合、通常の関数を取得して適用することはできません。


そして、ここでfmap助けを急いでいます。 fmap通りの男、 fmapはコンテキストについて多くのことを知っています。 彼はすでに、コンテキストにパックされた値に関数を適用する方法を知っています。 Just 2 (+3)を適用するとします。 fmap使用します。
 > fmap (+3) (Just 2) Just 5 




バム! fmapはその方法を示しました! しかし、彼はどのように関数を正しく適用するかをどのように知っていますか?

それでは、実際にファンクターとは何ですか?


ファンクターは型クラスです。 彼の定義は次のとおりです。


ファンクターは、 fmapがどのように適用されるかが決定されるデータ型です。 そして、これがfmap仕組みです:


だから私たちにできることは:
 > fmap (+3) (Just 2) Just 5 


また、 fmapファンクタである可能性があるため、この関数fmap魔法のように適用します。 Just and Nothing関数を適用する方法を定義します:
 instance Functor Maybe where fmap func (Just val) = Just (func val) fmap func Nothing = Nothing 


これは、 fmap (+3) (Just 2)を記述するときにバックグラウンドで発生することです。


そして、あなたは言う:「さて、 fmap 、しかしNothing適用しNothingください(+3) 。」


 > fmap (+3) Nothing Nothing 



ビル・オライリーは、おそらくファンクターには意味がない

The MatrixのMorpheusと同様に、 fmap何をすべきかを知っています。 あなたはNothingで始まり、 Nothingでも終わりました! これはfmap zenです。 そして今、一般にMaybeデータ型が存在する理由が明らかになりました。 ここで、たとえば、 Maybeせずに言語でデータベースへの書き込みをどのように処理しますMaybe
 post = Post.find_by_id(1) if post return post.title else return nil end 


Haskellの場合:
 fmap (getPostTitle) (findPost 1) 


findPostがメッセージを返す場合、 findPostを使用してヘッダーをgetPostTitleます。 彼がNothingを返すなら、私たちはNothingを返します! くそー、エレガント?
<$>fmap挿入形です。そのため、上記のコードの代わりに次のコードを見つけることができます。
 getPostTitle <$> (findPost 1) 


別の例を次に示します。関数をリストに適用するとどうなりますか?


リストもファンクターです! 定義は次のとおりです。
 instance Functor [] where fmap = map 


わかりました、わかりました、もう1つ(最後の)例:関数を別の関数に適用するとどうなりますか?
 fmap (+3) (+1) 


関数は次のとおりです。


そして、これは別の関数に適用される関数です:


結果は単なる別の機能です!
 > import Control.Applicative > let foo = fmap (+3) (+2) > foo 10 15 


関数もファンクターです!
 instance Functor ((->) r) where fmap fg = f . g 


また、関数にfmapを適用すると、関数を作成するだけです!

応用ファンクター


次のレベルは、アプリカティブファンクターです。 それらによって、私たちの価値はまだコンテキストに詰め込まれています(ファンクターの場合と同様):


しかし今、私たちの関数はコンテキストに詰め込まれています!


うん! これを始めましょう。 応用ファンクターは詐欺に関与しません。 Control.Applicativeは、 コンテキストでパッケージ化された関数をコンテキストで パッケージ化された値に適用する方法を知っている<*>を定義します


つまり
 Just (+3) <*> Just 2 == Just 5 


<*>を使用すると、興味深い状況につながる可能性があります。 例:
 > [(*2), (+3)] <*> [1, 2, 3] [2, 4, 6, 4, 5, 6] 




そして、ここにあなたが適用可能なファンクターの助けを借りてできることがありますが、普通のファンクターの助けを借りてはできません。 2つの引数を2つのパック値に取る関数をどのように適用しますか?
 > (+) <$> (Just 5) Just (+5) > Just (+5) <$> (Just 4) ???         JUST 


適用可能なファンクター:
 > (+) <$> (Just 5) Just (+5) > Just (+5) <*> (Just 3) Just 8 


Applicative Functorを技術的に押しのけます。 「大物は、任意の数の引数を持つ関数を使用できます」と彼は言います。 「 <$><*>で武装しているので、任意の数のアンパックされた引数を予期する関数を使用できます。 次に、すべてのパックされた値を彼女に渡し、パックされた結果を取得します! BWAHAHAHAHAHA!」
 > (*) <$> Just 5 <*> Just 3 Just 15 



応用ファンクタは、正規関数がどのように関数を適用するかを観察します

そしてはい! 同じことを行うliftA2関数があります。
 > liftA2 (*) (Just 5) (Just 3) Just 15 


モナド


モナドを学ぶ方法:
  1. コンピューターサイエンスで博士号を取得
  2. このセクションを読むときにそれらは必要ないので、彼らにnafigを投げてください!

モナドはプロットに新しいひねりを加えます。
ファンクターは、パックされた値に通常の関数を適用します。


適用可能なファンクターは、パック関数をパック値に適用します。


モナドは、パックされた値パックされた値戻す関数適用します。 モナドには関数>>= (「バインディング」と発音します( バインド ))があり、これを行うことができます。
この例を考えてみましょう:私たちの古き良きMaybeはモナドです:

ぶら下がりモナド

halfを偶数でのみ機能する関数とします。
 half x = if even x then Just (x `div` 2) else Nothing 




しかし、パックされた値を彼女に与えるとどうなりますか?


関数でパックされた値をプッシュするには、 >>=を使用する必要があります。 写真はこちら>>=


そして、これがどのように機能するかです:
 > Just 3 >>= half Nothing > Just 4 >>= half Just 2 > Nothing >>= half Nothing 


内部で何が起こっているのですか? Monadは別の型クラスです。 部分的な定義は次のとおりです。
 class Monad m where (>>=) :: ma -> (a -> mb) -> mb 


ここで>>=


だからMaybeモナドです:
 instance Monad Maybe where Nothing >>= func = Nothing Just val >>= func = func val 


しかし、貧しいJust 3に対してどのようなアクションが行われているのでしょうか。


入力にNothingを渡すと、さらに簡単になります。


一連の呼び出しをリンクすることもできます。
 > Just 20 >>= half >>= half >>= half Nothing 





かっこいい! そして今、 MaybeFunctorApplicative 、そしてMonad 1つになっていることがわかりました。
それでは、別の例に切り替えましょう: IOモナド:


特に、3つの機能。 getLineは引数を取らず、入力からユーザーデータを受け取ります。


 getLine :: IO String 


readFileは文字列(ファイル名)を取り、その内容を返します。


 readFile :: FilePath -> IO String 


putStrLnは文字列を取り、それを出力します:


 putStrLn :: String -> IO () 


3つの関数はすべて、通常の値(または値なし)を取り、パックされた値を返します。 したがって、 >>=を使用してそれらをチェーンできます!


 getLine >>= readFile >>= putStrLn 


はい、モナドショーの最前列のチケットがあります!
Haskellは、 do記法と呼ばれるモナドの構文糖衣も提供します。
 foo = do filename <- getLine contents <- readFile filename putStrLn contents 


おわりに


  1. ファンクターは、 Functor型クラスを使用して実装されるデータ型です
  2. Applicative Functorは、 Applicative型クラスを使用して実装されるデータ型です
  3. Monadは、 Monad型クラスを使用して実装されるデータ型です。
  4. 3種類すべてのタイプを使用して実装される可能性があるため、同時にファンクター、適用ファンクター、およびモナドです

3つの違いは何ですか?




だから、親愛なる友人(そして、この瞬間までに友人になったことを願っています)、私はモナドがシンプルでスマートなアイデア(tm)であることに全員が同意すると思います。 そして今、このガイドで喉を濡らした後、メルギブソンに電話してボトルを仕上げてみませんか? LYAHのモナドセクションをご覧ください。 Miranがこの資料を深める素晴らしい仕事をしてくれたので、私が言及しなかったことがたくさんあります。
さらに多くのモナドと写真が3つの便利なモナドにあります翻訳 )。

翻訳者から:
オリジナルへのリンク: http ://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html HabrはURLをカンマで誓うので、このように書きます。
そしてもちろん、翻訳に関するPMのコメントに非常に感謝します。

Source: https://habr.com/ru/post/J183150/


All Articles