fp tsから始まる
19157 ワード
ポストでは、我々は効果的なプログラムを作成することができます見た
プログラムF
プログラムG
組成
純粋な
純粋な
純粋な
この最後のケースを処理するために、我々はより強力な何かを必要とします
問題:入れ子になった文脈
もっと必要な理由を説明するために、いくつかの例を見てみましょう.
例
Twitterユーザーのフォロワーのフォロワーをリトライしたいと言います.
入れ子になった配列を平らにする必要があります.
The
例
数字リストの先頭の逆数を計算したいと言う
入れ子を平らにする必要がある
確かに、これらの型のコンストラクタ(および他の多くの)は、monadインスタンスを認めます
それで、モナドは何ですか?
これは、モナドがしばしば提示される方法です.
定義
モナドは3つのもので定義されます.
( 1 )タイプコンストラクタ
2)機能
関数 どこ
しかし、.なぜ?
私が最初にそのような定義を見た日に戻って、私の最初の反応は困惑でした.
すべてのこれらの質問は、私の頭で回っていました: なぜ、これらの2つの特定の操作と理由は、これらの種類がありますか? なぜ“flatmap”という名前ですか? なぜ法律?どういう意味ですか. しかし、何よりも、私はどこですか この投稿はそれぞれの質問に答えるようにします.
私たちの問題に戻りましょう:2つの効果的な関数の構成は何ですか?
(2つのkrouli矢、それらの構成は何ですか?)
私は、そのタイプが何であるかについて、わかりさえしません.
…を待つ.我々はすでに、すべての組成についての抽象化に遭遇した.私の言ったことを覚えていますか.
我々は、問題をカテゴリー問題に変えることができます:我々はKrestrli矢の構成をモデル化するカテゴリーを見つけることができますか?
クレーリ族
カテゴリーk(kdeliliカテゴリーという名前の)を作りましょう. オブジェクトはtsカテゴリの同じオブジェクトです. モーフィズムは、このように構築されています
(tsカテゴリーより上)
だから、何の組成になります
(TSカテゴリーの構成より、K構文の構成より下)
以来
だから、の組成の良い候補
どうやってこのような機能を構築できますか?さて、試してみよう!
我々がステップによる構成段階を造る中で
モナド定義のポイント(1)は
どこ
そして、現在、我々は動かれています:タイプの値を平らにすることができるFunctionインスタンスの法的操作はありません
そのような操作を定義できれば、我々は探している構成を得ることができる
プログラムF
プログラムG
組成
純粋な
純粋な
純粋な
効力のある
どこ
法律
最後の質問:法律はどこから来ますか?それらはtsに翻訳されたkのカテゴリー法だけです:
法
ケイ
TS
左のアイデンティティ
1 B∘
モナド
入れ子になったコンテキストの問題を示す例に戻ると、
結論
機能的プログラミングは、効果を備えた機能を構成するための普遍的な方法を提供します.
関数型プログラミングは本当に作文について
f: (a: A) => M<B>
純粋にn
-プログラムg
持ち上げるg
, 提供M
アプリケーションのインスタンスインスタンスを認めるプログラムF
プログラムG
組成
純粋な
純粋な
g ∘ f
効力のある純粋な
n
-アリーliftAn(g) ∘ f
どこliftA1 = lift
しかし、我々は1つの最後のケースを解決しなければなりません:両方のプログラムが有効であるならば、どうですか?f: (a: A) => M<B>
g: (b: B) => M<C>
このような「構図」とはf
and g
?この最後のケースを処理するために、我々はより強力な何かを必要とします
Functor
入れ子になったコンテキストで終わるのはかなり簡単ですから.問題:入れ子になった文脈
もっと必要な理由を説明するために、いくつかの例を見てみましょう.
例
M = Array
)Twitterユーザーのフォロワーのフォロワーをリトライしたいと言います.
interface User {
followers: Array<User>
}
const getFollowers = (user: User): Array<User> => user.followers
declare const user: User
const followersOfFollowers: Array<Array<User>> = getFollowers(user).map(getFollowers)
何か悪いところがあります.followersOfFollowers
は型Array<Array<User>>
でも欲しいArray<User>
.入れ子になった配列を平らにする必要があります.
The
flatten: <A>(mma: Array<Array<A>>) => Array<A>
関数のエクスポートfp-ts
便利になるimport { flatten } from 'fp-ts/Array'
const followersOfFollowers: Array<User> = flatten(getFollowers(user).map(getFollowers))
いいね他のデータ構造はどうですか?例
M = Option
)数字リストの先頭の逆数を計算したいと言う
import { Option, some, none, option } from 'fp-ts/Option'
import { head } from 'fp-ts/Array'
const inverse = (n: number): Option<number> => (n === 0 ? none : some(1 / n))
const inverseHead: Option<Option<number>> = option.map(head([1, 2, 3]), inverse)
opss、再びやった.inverseHead
は型Option<Option<number>>
でも欲しいOption<number>
.入れ子を平らにする必要がある
Option
s.import { isNone } from 'fp-ts/Option'
const flatten = <A>(mma: Option<Option<A>>): Option<A> => (isNone(mma) ? none : mma.value)
const inverseHead: Option<number> = flatten(option.map(head([1, 2, 3]), inverse))
すべての人々flatten
機能.それは偶然の一致ではなく、フードの下に機能的なパターンがあります.確かに、これらの型のコンストラクタ(および他の多くの)は、monadインスタンスを認めます
flatten
is the most peculiar operation of monads
それで、モナドは何ですか?
これは、モナドがしばしば提示される方法です.
定義
モナドは3つのもので定義されます.
( 1 )タイプコンストラクタ
M
インスタンスを認める2)機能
of
次の署名of: <A>(a: A) => HKT<M, A>
3)機能flatMap
次の署名flatMap: <A, B>(f: (a: A) => HKT<M, B>) => ((ma: HKT<M, A>) => HKT<M, B>)
注意:HKT
型はfp-ts
ジェネリック型コンストラクタを表す方法ですHKT<M, X>
型コンストラクタと考えることができますM
型に適用されるX
(i.e. M<X>
).関数
of
and flatMap
は三つの法則に従う必要がある:flatMap(of) ∘ f = f
(左)flatMap(f) ∘ of = f
(正体)flatMap(h) ∘ (flatMap(g) ∘ f) = flatMap((flatMap(h) ∘ g)) ∘ f
(結合度)f
, g
, h
すべての効果的な機能と∘
は通常の関数合成です.しかし、.なぜ?
私が最初にそのような定義を見た日に戻って、私の最初の反応は困惑でした.
すべてのこれらの質問は、私の頭で回っていました:
flatten
? 私たちの問題に戻りましょう:2つの効果的な関数の構成は何ですか?
(2つのkrouli矢、それらの構成は何ですか?)
私は、そのタイプが何であるかについて、わかりさえしません.
…を待つ.我々はすでに、すべての組成についての抽象化に遭遇した.私の言ったことを覚えていますか.
Categories capture the essence of composition
我々は、問題をカテゴリー問題に変えることができます:我々はKrestrli矢の構成をモデル化するカテゴリーを見つけることができますか?
クレーリ族
カテゴリーk(kdeliliカテゴリーという名前の)を作りましょう.
f: A ⟼ M<B>
我々は矢を描くf': A ⟼ B
イン・ケー(tsカテゴリーより上)
だから、何の組成になります
f'
and g'
Kで?それは、ラベルの付いた矢印ですh'
下記のイメージで(TSカテゴリーの構成より、K構文の構成より下)
以来
h'
からの矢ですA
to C
, 対応する関数h
からA
to M<C>
インTS
.だから、の組成の良い候補
f
and g
TSでは、以下のシグネチャを持つ有効な関数です.(a: A) => M<C>
.どうやってこのような機能を構築できますか?さて、試してみよう!
我々がステップによる構成段階を造る中で
モナド定義のポイント(1)は
M
関数のインスタンスを認めるので、lift
機能g: (b: B) => M<C>
機能するlift(g): (mb: M<B>) => M<M<C>>
(ここではシノニムを使いますmap
)どこ
flatMap
由来するそして、現在、我々は動かれています:タイプの値を平らにすることができるFunctionインスタンスの法的操作はありません
M<M<C>>
型の値にM<C>
, 追加が必要ですflatten
操作.そのような操作を定義できれば、我々は探している構成を得ることができる
h = flatten ∘ map(g) ∘ f
でも待ちます.flatten ∘ map(g)
フラットマップは、名前がどこから来るのです!h = flatMap(g) ∘ f
今すぐ私たちの“組成表”を更新することができますプログラムF
プログラムG
組成
純粋な
純粋な
g ∘ f
効力のある純粋な
n
-アリーliftAn(g) ∘ f
効力のある効力のある
flatMap(g) ∘ f
どこliftA1 = lift
アバウトof
? まあ.of
Kのアイデンティティ同形から来ます:Kの各々のアイデンティティ同形1 Aのために、1からの対応する機能がなければなりませんA
to M<A>
(i.e. of: <A>(a: A) => M<A>
).どこ
of
由来する法律
最後の質問:法律はどこから来ますか?それらはtsに翻訳されたkのカテゴリー法だけです:
法
ケイ
TS
左のアイデンティティ
1 B∘
f'
= f'
flatMap(of) ∘ f = f
正しいアイデンティティf'
∘ 1 A =f'
flatMap(f) ∘ of = f
結合性h' ∘ (g' ∘ f') = (h' ∘ g') ∘ f'
flatMap(h) ∘ (flatMap(g) ∘ f) = flatMap((flatMap(h) ∘ g)) ∘ f
モナド
fp-ts
インfp-ts
the flatMap
関数は、chain
, 基本的にはflatMap
引数を並べ替えてflatMap: <A, B>(f: (a: A) => HKT<M, B>) => ((ma: HKT<M, A>) => HKT<M, B>)
chain: <A, B>(ma: HKT<M, A>, f: (a: A) => HKT<M, B>) => HKT<M, B>
注意chain
から得られるflatMap
(とviceversa ).入れ子になったコンテキストの問題を示す例に戻ると、
chain
import { array, head } from 'fp-ts/Array'
import { Option, option } from 'fp-ts/Option'
const followersOfFollowers: Array<User> = array.chain(getFollowers(user), getFollowers)
const headInverse: Option<number> = option.chain(head([1, 2, 3]), inverse)
結論
機能的プログラミングは、効果を備えた機能を構成するための普遍的な方法を提供します.
関数型プログラミングは本当に作文について
Reference
この問題について(fp tsから始まる), 我々は、より多くの情報をここで見つけました https://dev.to/gcanti/getting-started-with-fp-ts-monad-6kテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol