PHPスクリプトのエンコード(もう一度)
29224 ワード
私がトランスフォームをサポートすることができて、冗長な宣言の必要性を減らすそのような方法で、タイプスクリプトでより高い親切なタイプ(HKTS)をコード化する新しい方法に熱心に書いていたとき、それはおよそ1年前でした.
記事は次のとおりです.https://www.matechs.com/blog/encoding-hkts-in-ts4-1
年にたくさん起こったEffect 今年、多くの新しい貢献者と多くの新しい生態系プロジェクトと私はより興奮することができませんでした.
すべての利益の背後には多くの努力があり、時には複雑にビットごとに取り組んで複数の段階に繰り返す必要があります簡単に見えるものに到達する.
これは、我々が集団的に何か単純な何年もの間逃した方法の物語です.
上記の記事を読んでみたいのなら、ここからゼロから始めます.
なぜ我々はHKTSが必要ですか?
モジュール間で共通の機能を実装したいなら、例えば以下の関数を取りましょう.
この動作を記述するためのインターフェイスを定義したいと思います.残念なことに、それはどのように明白ではありません.
つ目の夢を見ましょう
これまでのところ、単一のパラメータを持つデータ型のみが見られました
実際にはこれに一般的な解決策はありませんが、多くのアイデアが存在します.例えばScalaでは、型ラムダ(型パラメータ間のマッパのソート)を定義することができます.
夢を止めましょう
お話ししましょう
最近、私は、より良いデザインは、無関係なものについてあなたに話す必要を最小にするデザインであるとますます聞いていました、前のencodingsで、このリストは巨大です、しかし、私は現在、私が一つの「トリック」(信頼できる予想されたふるまいと確認される)についてあなたに話さなければならないだけであると言わなければなりません.
The
インターフェイスの中で参照することもできます
単一パラメータ符号化
上記の線に沿って何かを定義しましょう.
今我々は定義することができます
上記のように書くこともできます.
マルチパラメータ符号化
ここで本当に知っている唯一のことは
typeclassによる推論
完全に符号化
終わり
この符号化の完全なプロトタイプを見つけることができますhttps://github.com/mikearnaldi/hkt-new 変圧器の使用を含む
このポスト効果を書く瞬間に、まだこれに移動する古い符号化と進行を使用しますhttps://github.com/Effect-TS/core/issues/1005 .
記事は次のとおりです.https://www.matechs.com/blog/encoding-hkts-in-ts4-1
年にたくさん起こったEffect 今年、多くの新しい貢献者と多くの新しい生態系プロジェクトと私はより興奮することができませんでした.
すべての利益の背後には多くの努力があり、時には複雑にビットごとに取り組んで複数の段階に繰り返す必要があります簡単に見えるものに到達する.
これは、我々が集団的に何か単純な何年もの間逃した方法の物語です.
上記の記事を読んでみたいのなら、ここからゼロから始めます.
なぜ我々はHKTSが必要ですか?
モジュール間で共通の機能を実装したいなら、例えば以下の関数を取りましょう.
declare const mapArray:
<A>(self: Array<A>, f: (a: A) => B) => Array<B>
declare const mapTree:
<A>(self: Tree<A>, f: (a: A) => B) => Tree<B>
declare const mapOption:
<A>(self: Option<A>, f: (a: A) => B) => Option<B>
私たちは、上記の署名のどれだけが一般的であるかについて気付くことができます、実際、彼らは、彼らが目標とするタイプを除いて、すべて等しいですArray|Tree|Option
.この動作を記述するためのインターフェイスを定義したいと思います.残念なことに、それはどのように明白ではありません.
つ目の夢を見ましょう
interface Mappable<F<~>> {
readonly map:
<A, B>(self: F<A>, f: (a: A) => B) => F<B>
}
こうすると、declare const mapArray: Mappable<Array>["map"]
declare const mapTree: Mappable<Tree>["map"]
declare const mapOption: Mappable<Option>["map"]
実際には以下のように定義できます:declare const ArrayMappable: Mappable<Array>
declare const TreeMappable: Mappable<Tree>
declare const OptionMappable: Mappable<Option>
また、次のような汎用関数を実装することもできます.const stringify =
<F>(T: Mappable<F>) =>
(self: F<number>): F<string> =>
T.map(self, (n) => `number: ${n}`)
以下のようにします.const stringifiedArray: Array<string> =
stringify(MappableArray)([0, 1, 2])
用語を紹介するF<~>
はHigher Kinded Type
and interface Mappable<F<~>>
はTypeClass
.これまでのところ、単一のパラメータを持つデータ型のみが見られました
Option<~>
or Array<~>
, また、複数のパラメータを持つデータ型もありますEither<~, ~>
or Effect<~, ~, ~>
そして、私たちは同じセットアップでそれらを含むことを望みます.interface Mappable<F<~, ~, ~>> {
readonly map: <R, E, A, B>(
self: F<R, E, A>,
f: (a: A) => B
) => F<R, E, B>
}
しかし、我々は現在、誰のものを定義する問題がありますA
インEither
最初または2番目のパラメータ?我々は、どこでいくつかの規則を持つことができましたE
常に2番目と2番目ですR
常に最初でありA
常に最後のしかしそれはあまりにも柔軟性がありません.実際にはこれに一般的な解決策はありませんが、多くのアイデアが存在します.例えばScalaでは、型ラムダ(型パラメータ間のマッパのソート)を定義することができます.
夢を止めましょう
F<~>
有効なタイプスクリプトでさえありません、うまくいけば、我々は我々が持ちたいものの考えを得ました.お話ししましょう
最近、私は、より良いデザインは、無関係なものについてあなたに話す必要を最小にするデザインであるとますます聞いていました、前のencodingsで、このリストは巨大です、しかし、私は現在、私が一つの「トリック」(信頼できる予想されたふるまいと確認される)についてあなたに話さなければならないだけであると言わなければなりません.
The
this
タイプ単一化論理interface MyInterface {
readonly x?: unknown
}
type X = (MyInterface & { readonly x: number })["x"]
あなたは、タイプを正当に予想しますX
あるnumber
あれunknown & number = number
.インターフェイスの中で参照することもできます
this
タイプも期待できます.interface MyInterface {
readonly x?: unknown
readonly y: this["x"]
}
type Y = (MyInterface & { readonly x: number })["y"]
それは驚くべきことだy
常にunknown
代わりにthis
パラメータは常に拡張子でもカレント型を表すので特別ですX extends Y extends Z
, と定義されるものthis
インZ
はX
. これは、クラスやインタフェースのプレーンOOP継承のための使い方について考えるなら、かなり論理的です.単一パラメータ符号化
上記の線に沿って何かを定義しましょう.
interface HKT {
// will reference the A type
readonly _A?: unknown
// will represent the computed type
readonly type?: unknown
}
今では一般的なタイプを参照する方法が必要ですKind<F, A>
意味としてF<A>
, それはちょっとトリッキーです.type Kind<F extends HKT, A> =
F extends {
readonly type: unknown
} ?
// F has a type specified, it is concrete (like F = ArrayHKT)
(F & {
readonly _A: A
})["type"] :
// F is generic, we need to mention all of the type parameters
// to guarantee that they are never excluded from type checking
{
readonly _F: F
readonly _A: () => A
}
それから、interface ArrayHKT extends HKT {
readonly type: Array<this["_A"]>
}
type X = Kind<ArrayHKT, number>
そして、X
is number[]
.今我々は定義することができます
Mappable
以前からinterface Mappable<F extends HKT> {
readonly map:
<A, B>(self: Kind<F, A>, f: (a: A) => B) => Kind<F, B>
}
定義できます:const MappableArray: Mappable<ArrayHKT>
我々の署名をチェックすることができますMappableArray["map"]
そして、<A, B>(self: A[], f: (a: A) => B) => B[]
.上記のように書くこともできます.
const stringify =
<F extends HKT>(T: Mappable<F>) =>
(self: Kind<F, number>): Kind<F, string> =>
T.map(self, (n) => `number: ${n}`)
そして、仕事はされます.マルチパラメータ符号化
ここで本当に知っている唯一のことは
Kind
すべての型パラメータをそれぞれの分散で記述する必要があります.例えば、1つの入力とR、E、Aという2つの出力をサポートしたいとしましょう.interface HKT {
readonly _R?: unknown
readonly _E?: unknown
readonly _A?: unknown
readonly type?: unknown
}
type Kind<F extends HKT, R, E, A> =
F extends {
readonly type: unknown
} ?
(F & {
readonly _R: R
readonly _E: E
readonly _A: A
})["type"] :
{
readonly _F: F
readonly _R: (_: R) => void
readonly _E: () => E
readonly _A: () => A
}
interface Mappable<F extends HKT> {
readonly map:
<R, E, A, B>(
self: Kind<F, R, E, A>,
f: (a: A) => B
) => Kind<F, R, E, B>
}
interface ArrayHKT extends HKT {
readonly type: Array<this["_A"]>
}
const stringify =
<F extends HKT>(T: Mappable<F>) =>
<R, E>(self: Kind<F, R, E, number>) =>
T.map(self, (n) => `number: ${n}`)
declare const ArrayMappable: Mappable<ArrayHKT>
const res = stringify(ArrayMappable)([0, 1, 2])
typeclassによる推論
完全に符号化
Higher Kinded Types
そして、私たちはTypeClass
ライクMappable
, 推論を改善するためにはF
パラメータが設定されていない場合には、以下のようなオプションのパラメータを追加することによって行うことができます.interface TypeClass<F extends HKT> {
readonly _F?: F
}
interface Mappable<F extends HKT> extends TypeClass<F> {
readonly map:
<R, E, A, B>(
self: Kind<F, R, E, A>,
f: (a: A) => B
) => Kind<F, R, E, B>
}
終わり
この符号化の完全なプロトタイプを見つけることができますhttps://github.com/mikearnaldi/hkt-new 変圧器の使用を含む
ValidationT
, ReaderT
, など).このポスト効果を書く瞬間に、まだこれに移動する古い符号化と進行を使用しますhttps://github.com/Effect-TS/core/issues/1005 .
Reference
この問題について(PHPスクリプトのエンコード(もう一度)), 我々は、より多くの情報をここで見つけました https://dev.to/matechs/encoding-of-hkts-in-typescript-5c3テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol