もう䞀぀のモナドガむドパヌト4倚分モナドずリストモナド

マむク・ノァニ゚

このシリヌズの以前の蚘事では、モナドの抂念的基瀎を研究したしたが、議論はあたりにも抜象的でした。 モナドずは䜕か、なぜモナドが必芁なのかを理解できたので、特定のモナドを詳现に調べる時が来たした。 これは、前に芋た倚くの異なる蚈算抂念に察しお、 Monad型クラスの正しい化身を定矩するこずを意味したす。 知識を䜿甚しお、各堎合にモナドアプリケヌション挔算子>> = を介しおモナド構成を取埗し、モナドの法則を䜿甚しおreturnの定矩を導出したす。

たぶんモナド



通垞、Monadは䜿いやすく、実装し、理解しやすいため、Haskellのマニュアルで最初に玹介されるのが普通です。 最初に、 Maybeデヌタ型の定矩を芋おください。

デヌタ 倚分 a = Nothing | ただ


Maybeは特定のデヌタ型を取埗するために特定の型aが配眮される型コンストラクタヌであるず述べおいたす。 圌らはたた、 倚分 「倚態性」デヌタ型であり、意味は同じだず蚀っおいたす。 したがっお、 aがIntの堎合、次のようになりたす。

デヌタ 倚分 Int = Nothing | ちょうどint


䞊蚘の抜象的な定矩はすべおのタむプに適甚されるため、今だけこれを盎接蚘述する必芁はありたせん。

タむプaの倀は、存圚する堎合ず存圚しない堎合がありたす。 倀がNothingの堎合、「そうでない堎合」であり、 xのある倀に察しおJust xである堎合、これはxの 「ちょうど」倀です。 これは、0個の芁玠たたは1個の芁玠があるコンテナず考えるこずができたす。 芚えおおいおください私はか぀おモナド倀が誀っおコンテナずしお提瀺されるこずがあるず蚀っおいたした。これが事実です。

倚分型ポリモヌフィック型は、出力倀ずしお䜕かを生成するか、クラッシュしお倀を返すこずができない「拡匵関数」のモデルずしお䜿甚できるずいう点で䟿利です。 ぀たり、そのような関数は倱敗する可胜性がありたす。これは次のように曞かれおいたす。

f :: a- > たぶん b


関数fは、タむプaの倀を取り、 Nothing 倱敗の兆候たたは倀Just xを返したす xはタむプbを 持ちたす。 fのような関数はMaybeモナドで動䜜し、そのような2぀の関数の構成は次のずおりです。

f :: a- > たぶん b -fがどこかで定矩されおいるず仮定する
g :: b- > たぶん c -gがどこかで定矩されおいるず仮定する

h :: a- > たぶん c -fずgの単項合成
h = f > => g- 芚えおおいおください> =>は単項合成の挔算子です


すべおのモナドは型コンストラクタでなければならない、ず蚀いたした。 倚分型コンストラクタなので、ここではすべおがうたくいきたす。 しかし、 たぶんモナドになるためには、 Monad型クラスのむンスタンスを䜜成する必芁がありたす。぀たり、次の定矩を入力する必芁がありたす。

むンスタンス Monad たぶん どこ
 >> =  = {-定矩>> =たぶん-}
return = {-たぶんリタヌンの定矩-}


Maybeにどのように蚭定>> =しお戻るこずができたすか

たず、 >> =の定矩フレヌムワヌクを蚘述し、 倚分a型の巊オペランドの2぀の可胜なケヌスをカバヌしたす。

なし>> = f = {-远加する必芁がありたす-}
x >> = f = {-远加する必芁がありたす-}


xはタむプaです。 定矩の巊偎は別の方法で曞くこずができたす

 >> = 䜕もf = {-远加する必芁はありたせん-}
 >> =   Just x  f = {-远加が必芁-}


しかし、挔算子>> =が関数ずしおではなく挔算子ずしお指定されおいるず、Haskellはこれを蚱可したす。

この定矩を完了するために、 Maybeモナドのモナド構成から䜕が欲しいか考えおみたしょう。 関数fずgを䜿甚しお䟋をずり、それらを単項結合し、関数hを取埗したす。

f :: a- > たぶん b
g :: b- > たぶん c
h :: a- > たぶん c
h = f > => g


匕数を関数fに枡し、 Nothingを返す぀たり、倱敗する堎合、関数hは䜕を返す必芁がありたすか

f x =なし
h x =  f > => g  x = ???


fxがNothingを返す堎合、匏関数f の䞀郚が結果を返すこずができなかった堎合、匏党䜓関数h が結果を返せないため、 hもNothingを返す必芁があるこずは明らかです。 hが倀を返すずきの唯䞀のオプションは、 fが結果を返すずき yを呌び出したしょう、関数gに枡され、 gyも正しい結果になりたす。 fたたはgが倱敗するず、 hも倱敗したす。぀たり、 hxの蚈算はNothingになりたす。

これを念頭に眮いお、 hの定矩から次のようになりたす。

h = f > => g
h = \ x ->  f x >> = g  -同等定矩> =>から
h x = f x >> = g- 同等
-f x == Nothingず仮定する
h x = なし>> = g 
=なし
-このように
なし>> = g =なし


これで、挔算子>> =がNothing匕数にどのように反応するかがわかりたした-単に同じNothingを返すだけです

なし>> = f =なし
x >> = f = {-远加する必芁がありたす-}


ここでgをfに眮き換えたこずに泚意しおください。これは正しいこずです。関数の名前は重芁ではないからです。 実際には、可胜な堎合は通垞関数名を取り陀き、次のように特別な挔算子_ アンダヌスコアに眮き換えたす。

なし>> = _ =なし


これは、定矩で関数fを䜿甚するため、2番目の匏では実行できたせん。

それでは、他の方法に行きたしょう。 fx が倱敗しない堎合、結果は䞀郚のyに察しおJust yの倀になりたす。 Just yからyの倀を「アンパック」する必芁があり、それを関数gに枡したす。gyは関数h党䜓の結果です。

h = f > => g
h = \ x ->  f x >> = g  -同等定矩> =>から
h x = f x >> = g- 同等
-f x == Just yず仮定する
h x = ちょうどy >> = g 
= g y


これにより、定矩の2番目の郚分が埗られたす。

なし>> = f =なし
ちょうどx >> = f = f x


yをxに 、 gをfに眮き換えたこずに泚意しおください。 繰り返したすが、倉数ず関数の名前は䞀貫しおいる限り重芁ではありたせん。

これで、 Maybeモナドの>> =挔算子の定矩が終了したす。 次に、このモナドのリタヌンを取埗する必芁がありたす。

return x = ???


xの任意の倀に察しお 。 どのようなオプションがありたすか 私たちはそれを蚀うこずができたす

return x =なし


任意のxに察しお 。 ただし、これを行うずモナド法に違反したす。

return x >> = f == f x
䜕もない>> = f == f x
䜕もない== f x- 間違っおいたす


少なくずも䞀郚の fxが Nothing でないず仮定するずたずえば、モナド関数fx = Just xを考慮しお、゚ラヌが発生したす。 別のオプションがありたす

return x =ちょうどx


そしお、それはモナドの法則を満たしたす

return x >> = f
=  Just x  >> = f- 定矩により、Maybeモナドを返す
= f x- 定矩により>> =モナドの堎合
-最初のモナド法の実装

ちょうどx >> = return
= return x- 定矩により>> =たぶんモナド
=ちょうどx- 定矩により、Maybeモナドを返す
-第2モナド法の実装

䜕もない>> = 戻る
=なし-定矩により>> =モナドの堎合
-第2モナド法の実装


法埋が尊重されたら、このオプションを遞択したす。 Maybeモナドの完党な定矩は次のようになりたす。

むンスタンス Monad たぶん どこ
return x =ちょうどx

なし>> = f =なし
ちょうどx >> = f = f x


わあ 最初のモナドを䜜成したした

私たち自身を保護するために、それが第3モナド法を満たしおいるこずを怜蚌したす。

 mv >> = f  >> = g == mv >> =  \ x ->  f x >> = g  


たず、mv = Nothingの堎合の法則を確認したす。

なし>> = f  >> = g- 巊偎
=なし>> = g- 定矩により>> =
=なし-定矩により>> =

なし>> =  \ x ->  f x >> = g   -右偎
=なし-定矩により>> =


OK、チェックは成功したした。 次に、 mv = Just vで機胜するかどうかを芋おみたしょう。ここで、 vは倀です。

  Just v  >> = f  >> = g- 巊偎
= f v >> = g- 定矩により>> =

ちょうどv  >> =  \ x ->  f x >> = g   -右偎
=  \ x ->  f x >> = g   v- 定矩により>> =
= f v >> = g- 関数の通垞の䜿甚ベヌタ削枛


そしおたた成功。 法埋が斜行されおいたす これは本圓にモナドの正しい定矩かもしれたせん そしお芳客は倢䞭になりたす

このすべおのポむントは䜕ですか これは、 Maybeモナドのモナド関数の束を簡単に結合できるこずを意味したす。 なぜこれが重芁なのか疑問に思うかもしれたせん。 Maybeモナドの倚くのモナド関数、぀たり倱敗する可胜性のある関数を想像するこずはたったく難しくありたせん。 タむプがInt-> Maybe Intであるずしたしょう。 同様の3぀の機胜を次に瀺したす。

f :: Int- > 倚分 Int
f x = if x ` mod` 2 == 0 then Nothing else Just  2 * x 

g :: Int- > 倚分 Int
g x = if x ` mod` 3 == 0 then else Nothing Just  3 * x 

h :: Int- > 倚分 Int
h x = if x ` mod` 5 == 0 then else Nothing Just  5 * x 


それらを1぀の関数に結合したいず思いたす。これは、 f 、 g 、 hの順に適甚した結果です。

k :: Int- > 倚分 Int


たた、3぀の関数のいずれかが倱敗した堎合、関数kはNothingを返す必芁がありたす。 この関数は、2、3、たたは5で割り切れる敎数でない堎合、入力数に30を掛けたす割り切れる堎合、関数はNothingを返したす。

前の資料から、それをよく理解しおいれば、モナド合成を介しおkを指定できるこずは明らかです。

k = f > => g > => h


たたは、 >> =挔算子を䜿甚できたす。

k x = f x >> = g >> = h


たたは、 do- abstractが奜きかもしれたせん

k x = do y < -f x
z < -g y
h z


誰でも蚀えるこずは簡単です。 {1原文では、「任意の方法でスラむスする」ずいう氞続的な衚珟で、意味が䌌おいたす。 -泚 あたり。}

䞀般に、関数hはモナド構造なしで完党に定矩できたす;このようになりたす

k x = ケヌス f x
なし->なし
ちょうどy- > ケヌス g y の
なし->なし
ちょうどz- > h z


なぜモナドが重芁なのかは明らかです。 耇数のMaybe関数をチェヌン化するこずにより、コヌドを劇的に簡玠化したす。 この圢匏で10個のMaybe関数を構成するための倧たかな非モナドコヌドを想像しおください。 右偎に非垞に倧きなむンデントがあるず、読みやすさがひどく圱響を受け、入れ子になったcase匏の迷路では蚈算の䞀般的な構造が倱われたす。 しかし、モナドの助けを借りお、10個の関数の構成は簡単に曞かれおいたす

f11 = f1 > => f2 > => f3 > => f4 > => f5 > => f6 > => f7 > => f8 > => f9 > => f10


たたは >> =を䜿甚

f11 x = f1 x >> = f2 >> = f3 >> = f4 >> = f5 >> = f6 >> = f7 >> = f8 >> = f9 >> = f10


モナドを䜿甚するず、モナド関数の構成は、通垞の非モナド関数の構成ず同じくらい簡単です。

モナドは基本的な抂念を説明するのに非垞に圹立぀かもしれたせんが、混乱させる可胜性がありたす倚くの人々は、モナドの唯䞀の圹割は非機胜蚈算、぀たり入力/出力コン゜ヌルたたはファむルでを凊理するこずであるず誀っお信じおいたす、可倉グロヌバル状態など。 そしお、いく぀かのモナド蚈算がモナドなしで同じ成功で実行できるこずを瀺したした。 モナドは必須のものではなく、 非垞に䟿利であるこずがわかりたす。 そのため、非機胜コンピュヌティング甚のモナド IOを䜿甚 を発明した圓初の理由にもかかわらず、はるかに倧きな適甚性があるこずがわかりたした。 このため、モナドは良いです。

次のモナドに移りたしょう。

モナドリスト リスト



たぶんあなたがモナドが奜きなら、あなたはリスト・モナドさえ愛するでしょう。 ;-)この堎合、次の定矩を入力したす。

むンスタンス Monad [ ] ここで
 >> =  = {-リストの定矩>> =-}
return = {-リストの戻り倀の定矩-}


空のリスト[]を衚すには、リスト型コンストラクタヌを䜿甚するこずに泚意しおください。 これは小さなハックですHaskellのリストに察しお特別な構文サポヌトが提䟛されたす。 しかし、やるべきこずは䜕もありたせん。

すべおのモナドず同様に、最初のタスクはこのモナドのモナド関数が䜕であるかを理解するこずです。 リストの堎合、単項関数fは次のようになりたす。

f :: a- > [ b ]


 [b]は、もちろん、「タむプbの芁玠のリスト」を意味したす。 モナド関数の䞀般化された定矩は次のように曞かれおいるこずを思い出しおください

f :: a- > m b


䞀郚のモナドmに぀いおは、型コンストラクタである必芁がありたす。 リストはモナドの明らかな候補です。「リスト」は型コンストラクタであるためです構文がHaskellに組み蟌たれおいる堎合でも。 オプションで、リストを自分で定矩できたす。

デヌタリストa = Nil | 短所リストa 


それに察するモナド関数のタむプはそれに応じお芋えるでしょう

f :: a- >リストb


ただし、暙準の構文は匕き続き䜿甚したす。

この皮の機胜は䜕ですか 通垞、これらは、タむプaの入力倀を受け取り、1぀の䟿利なコンテナヌリストに収集されたタむプbの倀の束を生成する関数ずしお理解されたす。 たた、コンテナのように芋えるモナドがありたす。それらを倚くの倀を返す関数ず考える別の方法、぀たり、そのような関数は「1぀の」異なる倀の束を返したす。 ここではありたせんが、䞊列凊理を意味するため、「䞊列」ずいう意味ではありたせん。耇数の出力倀は単なるリストアむテムです。 次のような関数を䜿甚するず、䟿利なパヌスペクティブが開きたす。

f :: Int- > [ Int ]
g :: Int- > [ Int ]


ここでは、 fずgの䞡方が同じInt倀を取り、倚くのInt倀を返したす。 しかし、関数fの各結果を取埗しお、関数gの各結果に適甚し、アプリケヌションの結果を収集する堎合はどうでしょうか。 関数gおよびfの結果リストから各芁玠をアンパックせずに、これを盎接行うこずができれば玠晎らしいでしょう。 そしお、これはリストモナドを䜿甚しお行うこずができたす。

これらの関数のより具䜓的な䟋に移りたしょう

f :: Int- > [ Int ]
f x = [ x - 1 、 x 、 x + 1 ]

g :: Int- > [ Int ]
g x = [ -x 、 x ]


これら2぀の関数をどのように「構成」したすか fxはリストを返し、各芁玠にgを適甚するには、 map関数が必芁です。

f 10- > [ 9、10、11 ]
マップ g  f 10  -> [ [ -9、9 ] 、 [ - 10、10 ] 、 [ - 11、11 ] ]


この新しい結果は興味深いものですが、 fずgの合成にはなりたせん。異なるタむプ Intリストだけでなく、 Intリストのリストがあるためです。 concat関数を䜿甚しお単玔なリストに滑らかにするこずができたすリストを1぀に単玔に連結したす。

-連結タむプに特に泚意しおください[[a]]-> [a]
concat  map g  f 10   -> [ -9、9、-10、10、-11、11 ]


敎数にfを適甚し、次にfの埌に起こったこずにgを適甚するこずによっお生成されたすべおの結果のセットを埗たした。 fずgをここで倚くの結果を生成する関数ず考える堎合、それらの出力倀はfを䜿甚しおから次にgを䜿甚するすべおの可胜なセットになりたす。 これを図で衚すこずができたす。

                   g |  -9
            |  9 ----> |
            |  |  9
            |
        f |  g |  -10
   10 ----> |  10 ----> |
            |  |  10
            |
            |  g |  -11
            |  11 ----> |
                       |  11 


fずgの構成は、 fずgの間のすべおのパスのセットであるこずが明確にわかりたす。

奇劙なこずに、リストモナドに察しお挔算子>> =を定矩したした 次のように蚭定されたす。

-mv :: [a]
-g :: a-> [b]
mv >> = g = concat  map g mv 


ここで、 mvはリストモナドのモナド倀ですタむプaの倀のリストにすぎたせん。 前の䟋では、 mvはf 10の蚈算結果です。 定矩は空のリスト[]に察しおも機胜したす。関数を空のリストにマッピングするず空のリストが埗られ、空のリストの連結も垞に空のリストになるためです。 結果は、挔算子>> =の非垞に単玔な定矩です。

[GHCファンぞの泚意GHCコンパむラの>> =挔算子は、同じこずを行いたすが、より効率的か぀異なる方法で実装されるず考えおいたす。]

このモナドの戻り倀を蚭定する方法は モナドのリストの倀を、倚くの倀を返す「アクション」ず考えおみたしょう。 他のモナドのように、 returnはナニット関数ず同等でなければならないこずを思い出しおください。 リストモナドの単䞀の関数に盞圓するものは䜕ですか 倀を取り、「蚈算」の埌、単にその倀を返す「アクション」を返す必芁がありたす。 そのため、 returnは単に空のリストを返すこずができないこずに気付きたした。 returnに぀いお次のようなものを想定するのは合理的です。

return :: a- > [ b ]
return x = [ x ]


぀たり、 returnは、単䞀の倀からリストを芁玠的に䜜成したす。 この堎合、モナドの法則が順守されおいるかどうかを確認したす。

-f :: a-> [b]
-x :: a
return x >> = f = concat  map f  return x   -定矩により>> =
= concat  map f [ x ]  -定矩により
= concat [ f x ] -定矩マップにより
= f x- 定矩により、連結
-最初のモナド法の実装

-mv :: [a]
mv >> = return = concat  map return mv  -定矩により>> =
= concat  map  \ x- > [ x ]  mv  -定矩により
-2぀のケヌス
-ケヌス1mv == []
= concat  map  \ x- > [ x ]  [ ]  -定矩により、mv
= concat [ ] -定矩によりマップ
= [ ] -定矩によりconcat
= mv- 定矩によりmv
-ケヌス2mv == [v1、v2、...]
= concat  map  \ x- > [ x ]  [ v1 、 v2 、 ... ]  -定矩により、mv
= concat [ [ v1 ] 、 [ v2 ] 、 ... ] -定矩によりマップ
= [ v1 、 v2 、 ... ] -定矩によりconcat
= mv- 定矩によりmv
-第2モナド法の実装


さお、モナドの2぀の法則が蚌明されおいたす。 リタヌンの他の定矩を詊しおみるずよい堎合がありたす リタヌンが返される堎合、たずえば特定のリスト[0、2、3] 、たたは匕数のコピヌを無限に返す堎合。これらはすべおモナドの法則に違反しおいるこずがわかりたす。 これは、モナドの法則を実践する良い方法です。

リストを実際のモナドず呌ぶ前に、3番目のモナドの法則を蚌明するこずが残っおいたす。 それは蚀わなければならない、それはより難しいが、ずにかくしようずしたす。 タスクを簡玠化するために、3番目のモナド法則モナド構成で定矩の「快適な」圢匏を取りたす。 たず、リストの単項合成の定矩が必芁です。

-3番目のモナド法快適なバヌゞョン
 f > => g  > => h = f > =>  g > => h 
-定矩により
f > => g = \ x- > f x >> = g
-リストモナドの定矩>> =を䜿甚したす。
f > => g = \ x- > concat  map g  f x  
-構成挔算子。を䜿甚しお匏を曞き換えるこずができたす。
f > => g = concat マップ g 。 f


さらに、 concatおよびmap関数のいく぀かのプロパティを䜿甚したす。 あなたは今のずころ圌らを信仰に連れお行かなければならないでしょう。 次に、それらを取埗する方法を瀺したす。

-方皋匏1
map  f。g  = マップ f 。 地図 g
-方皋匏2
マップ f 。 concat = concat 。 マップ  マップ f 
-方皋匏3
concat 。 concat = concat 。 地図 連結


以前、ドット。は玔粋な合成挔算子であるず蚀いたした。 関数、぀たりマップfのような匏を適甚するよりも優先順䜍が䜎くなりたす。 マップgは平均のみマップf。 マップg 。 Haskellプログラマヌは通垞、可胜であれば括匧を取り陀きたす。 たた、たずえば、 map f関数は、実際には2぀の匕数を持぀マップ関数リストアむテム甚の関数ずリスト自䜓であるこずを理解するこずも重芁です。 カリヌ化に぀いお話しおいたこずを思い出すず、 マップfは1぀のリストを取埗しお別のリストを返す関数であり、 fは各芁玠に適甚されおいるず掚枬できたす。 今からカレヌをたくさん䜿いたす。

したがっお、これたでに述べられたこずをすべお考慮に入れた蚌拠の結論

 f > => g  > => h
=  concat。map g。f  > => h- 定矩により> =>
= concat 。 マップ h 。  concat。map g。f  -定矩により> =>
= concat 。 マップ h 。 concat 。 マップ g 。 f- 䞍芁な角かっこを削陀する

f > =>  g > => h 
= f > =>  concat。map h。g  -定矩により> =>
= concat 。 map  concat。map h.g  。 f- 定矩により> =>
= concat 。 map   concat。map h  .g  。 f は同等の倉換です
= concat 。  map  concat。map h   。  マップ g  。 f- 匏1による
= concat 。 マップ  連結 マップ h  。 マップ g 。 f- 䞍芁な角かっこを削陀する
= concat 。 地図 連結 地図  地図 h  。 マップ g 。 f- 匏1による


次のこずを瀺す必芁がありたす。

concat 。 マップ h 。 concat = concat 。 地図 連結 地図  地図 h 


それを蚌明したしょう。

-明確にするために括匧を远加したす。
concat 。  map h。concat  = concat 。 地図 連結 地図  地図 h 
-匏2によるず
concat 。 concat 。 map  map h  = concat 。 地図 連結 地図  地図 h 
-明確にするために括匧を远加したす。
 concat。concat  。 map  map h  = concat 。 地図 連結 地図  地図 h 
-匏3に埓っお
concat 。 地図 連結 map  map h  = concat 。 地図 連結 地図  地図 h 


そしおこれで終わりです。 ふう 実際、Haskellistsがこれを行うこずはめったにありたせんが、疑わしいモナドが本圓にモナドであるこずを瀺す蚌拠が必芁です。

限界ノヌト マップ/連結によるアむデンティティの導出匏1、2、および3

準備する

身元の蚌明を進める前に、他のいく぀かの蚌明をする必芁がありたす数孊は難しい。 それらをリストしたす。

-匏4
concat  xxs  = x ++ concat xs
-匏5
concat  x ++ y  = concat x ++ concat y
-匏6
map f  x ++ y  = map f x ++ map f y


匏4はconcatの定矩から埗られたす。 匏5は、匏4を䜿甚したxの垰玍法によっお簡単に蚌明されたす。

-ベヌスケヌスx-空のリスト
concat  [ ] ++ y  = concat [ ] ++ concat y
concat y = [ ] ++ concat y- 定矩によりconcat []
concat y = concat y- 定矩により++
-そうです。

-誘導リストxは空ではありたせん。 x1はリストの先頭です。 xsはリストの末尟です。
concat   x1xs  ++ y 
= concat  x1  xs ++ y   -定矩により++
= x1 ++ concat  xs ++ y  -匏4
= x1 ++ concat xs ++ concat y- 垰玍的仮説

concat  x1xs  ++ concat y
= x1 ++ concat xs ++ concat y- 匏4
-蚌​​明する必芁があったのは事実です。


匏6は同じ方法で蚌明できたす。

-ベヌスケヌスx-空のリスト
map f  [ ] ++ y  = map f [ ] ++ map f y
map f y = [ ] ++ map f y
map f y = map f y
-そうです。

-誘導リストxは空ではありたせん。 x1はリストの先頭です。 xsはリストの末尟です。
マップ f  x ++ y 
= マップ f   x1xs  ++ y 
= map f  x1  xs ++ y   -定矩により++
= f x1 map f  xs ++ y  -mapで定矩されおいる
= f x1  map f xs ++ map f y  -垰玍的仮説
=  f x1 map f xs  ++ map f y- 定矩により++
= map f  x1xs  ++ map f y -mapで定矩されおいる
= map f x ++ map f y- 定矩によりx
-蚌​​明する必芁があったのは事実です。


これで、方皋匏1、2、および3を蚌明したす。

匏1

map  f。g  = マップ f 。 地図 g


mapの定矩だけでなく、䞡偎の暗黙のリスト匕数に垰玍法を䜿甚したす 。

-基本ケヌス空のリスト
map  f。g  [ ] = [ ]
 マップ f 。 マップ g  [ ] = マップ f  マップ g [ ]  = マップ f [ ] = [ ]
-OK

-誘導空でないリスト
マップ  f。g   xxs 
=   f。g  x   map  f。g  xs  -定矩マップ
=  f  g x    map  f。g  xs  -定矩により。
 マップ f 。 マップ g   xxs 
= map f  map g  xxs   -定矩により。
= map f   g x   map g xs   -定矩によりマップ
=  f  g x    map f  map g xs   -定矩によりmap
=  f  g x      map f。map g  xs  -定矩により。
=  f  g x    map  f。g  xs  -垰玍的仮説
-蚌​​明する必芁があったのは事実です。


匏2

マップ f 。 concat = concat 。 マップ  マップ f 


垰玍法で蚌明する

-基本ケヌス空のリスト
 map f。concat  [ ] = map f  concat [ ]  = map f [ ] = [ ]
 concat。map  map f   [ ] = concat  map  map f  [ ]  = concat [ ] = [ ]
-OK

-誘導空でないリスト
 map f。concat   xxs 
= map f  concat  xxs   -定矩により。
= map f  x ++ concat xs  -匏4
= map f x ++  map f  concat xs   -匏6
= map f x ++   map f。concat  xs  -定矩により。
= map f x ++   concat。map  map f   xs  -垰玍的仮説
= map f x ++ concat  map  map f  xs  -定矩により。

 concat。map  map f    xxs 
= concat  map  map f   xxs   -定矩により。
= concat  map f x map  map f  xs  -定矩によりmap
= map f x ++ concat  map  map f  xs  -匏4
-蚌​​明する必芁があったのは事実です。


匏3

concat 。 concat = concat 。 地図 連結


い぀ものように、誘導を䜿甚したす。

-基本ケヌス空のリスト
 concat。concat  [ ] = concat  concat [ ]  = concat [ ] = [ ]
 concat。map concat  [ ] = concat  map concat [ ]  = concat [ ] = [ ]
-そう

-誘導空でないリスト
 concat。concat   xxs 
= concat  concat  xxs   -定矩により。
= concat  x ++ concat xs  -匏4
= concat x ++ concat  concat xs  -匏5

 concat。map concat   xxs 
= concat  map concat  xxs   -定矩により。
= concat  concat x map concat xs  -mapで 定矩されおいる
= concat x ++ concat  map concat xs  -匏4
= concat x ++  concat。map concat  xs- 定矩により。
= concat x ++  concat。concat  xs- 垰玍的仮説
= concat x ++ concat  concat xs  -定矩により。
-蚌​​明する必芁があったのは事実です。



リストモナドが本圓にモナドであるこずを疑う䜙地がないこずを願っおいたす。 ;-)

そしおもちろん、ここで最も興味深い質問はこれですモナドなしでは難しいリストモナドで䜕ができるでしょうか 簡単な䟋を次に瀺したす。合蚈が7である1〜6の数字のペアをすべお芋぀けたす数字はサむコロなど。 リストモナドを䜿甚するず、問題を解決するのは簡単です。

-<font color = blue> do </ font>衚蚘を䜿甚したす。
do n1 <- [ 1 .. 6 ]
n2 <- [ 1 .. 6 ]
n1 + n2 == 7の 堎合、  n1 、 n2  else [ ]を 返し たす
-結果[1,6、2,5、3,4、4,3、5,2、6,1]


たた、 do衚蚘なしで曞き換えるこずもできたすが、明確ではありたせん。

[ 1 .. 6 ] >> = \ n1- >
[ 1 .. 6 ] >> = \ n2- >
n1 + n2 == 7の 堎合、  n1 、 n2  else [ ]を 返し たす


どのように機胜したすか 座っお>> =に関連するすべおの蚈算をトレヌスし、リストに戻る必芁がありたすが、ここでは指の説明を瀺したす。 したがっお [1..6]はリストモナドのモナド倀であり、 n1は䞀床にすべおのモナド倀を実行したす 。 n2-たったく同じ。 そしお、合蚈が正しいすべおのペアn1、n2が返されたす。 これは、あたかもそれらが1぀の芁玠であるかのように、すべおの芁玠で関数を蚈算する方法です。 これがモナドリストの本質です。

Haskellプログラミングの知識が豊富であれば、おそらく頭の䞭でサむレンが聞こえたでしょう。 「なんおこずだ」私はあなたのdigりを聞いた。 「なぜリスト内包衚蚘を䜿甚しないのですか」そしお本圓に

[  n1 、 n2  | n1 <- [ 1 .. 6 ] 、 n2 <- [ 1 .. 6 ] 、 n1 + n2 == 7 ]


リストモナドずリストゞェネレヌタヌの機胜は同じです。 この構文たたはその構文の遞択は蚭定に䟝存し、タスクによっお決定するこずもできたす。 圌の蚘事「Comprehending Monads」では、 Phil Walder 圌の倚くの蚘事のようにタむトルにしゃれがありたすは、リストゞェネレヌタヌの構文を任意のモナドに拡匵するこずさえ提案したした。 それにもかかわらず、この提案は珟圚の蚘録を支持しお拒吊されたした。

リストモナドは、リストゞェネレヌタヌの単なる代替手段ではありたせん。 䞀方では、あらゆるモナドの化身ず連携する非垞に䞀般的な関数がたくさんありたす。 リストモナドでも動䜜したす。 䞀方、 MonadPlusず呌ばれるMonad型クラスには拡匵機胜がありたす。 モナドの機胜を補完したす具䜓的には、モナドの「れロ」芁玠を定矩し、2぀のモナド倀を「远加」する操䜜を導入したす。 リストはMonadずMonadPlusの䞡方の化身によっお䜜成されたす。぀たり、 MonadPlusの共通機胜はリストでも機胜したす。 たずえば、 concat関数の䞀般化-リストを含むMonadPlusのすべおのむンカネヌションで機胜するmsum 関数 がありたす。倚くのデヌタ型で機胜できるが、各型に個別に指定しない䞀般化機胜を䜿甚するのは玠晎らしいこずです。 これは明らかな勝利です。

次回


次の蚘事では、゚ラヌを远跡できるモナドに぀いお説明したす。

内容

パヌト1基本
パヌト2関数>> =およびreturn
パヌト3モナドの法則
パヌト4倚分モナドずリストモナド

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


All Articles