Tkr Blog

Posts about "typelevelprogramming"

All tags
2020/09/16
対象読者 明大FMSのEP演習という授業で発表した内容の補足資料なので、同大の同級生を対象読者に基本的なところから解説しています。言語実装をしたことある人にとっては知っている話が多いかと思います。 ソースコード https://github.com/kgtkr/BarrageLCL ドキュメントもここにあります。今回はd8d1412をベースに解説していきます。 BarrageLCLの概要 Processing製の3D弾幕生成ライブコーディング言語です。実行環境だけでなく、編集環境も用意されています。自作言語×自作エディタですね。 以下のコードを見てください。 このコードは毎秒15回、初速度を (100cos(0.2i), 100sin(0.2i), 200sin(0.1i)) に、色を赤に設定して弾を発射するというコードです。i は何回目の実行かを表す変数です。 すると以下のように弾が発射されます。 なぜこれを? EP演習第一回のオープニングパフォーマンスで見たライブコーディング言語が面白かったことと、夏休みのEP演習で3D空
2020/09/02
初めに TypeScriptの型システムはチューリング完全なので何でも計算できます。 例えば繰り返し。 type Repeat<T, N extends number, R extends any[] = []> = R["length"] extends N ? R : Repeat<T, N, [T, ...R]>; // type A = ["x", "x", "x", "x", "x", "x", "x", "x", "x", "x"] type A = Repeat<"x", 10>; わーい。ちょっと数増やすか… // error TS2589: Type instantiation is excessively deep and possibly infinite. type A = Repeat<"x", 100>; あれ?(つらい) 再帰制限解除したいですね。しましょう。 注意 当然ですがプロダクトで使うことは想定していません、やめましょう。 バージョンなど [email protected]
2019/04/15
When type level programming, various errors occur.So we need to suppress it. This article introduces two ways to suppress errors. I checked with v3.4.2. Suppress type constraint error There are operations in TS that can only be of the type that satisfies the condition. Here are some examples. type F<T extends any[]> = T; type X = F<A>;// A require to extends any[] type Y = B["x"]// B require object type and have roperty named `x` However, even if it is known that the con
2019/04/15
TypeScriptの型レベルプログラミングでは様々な型エラーが発生するため、それを抑制しながら作っていかなければいけません。 今回はエラーを回避するテクニックを2つ紹介します。 v3.4.2で動作確認をしています。 型制約エラーを抑制する TSには型の型のようなものがあり、それを満たす型にしかできないような操作があります。 いくつか例を挙げます。 type F<T extends any[]> = T; type X = F<A>;// Aはany[]を継承していなければいけない type Y = B["x"]// Bはオブジェクト型で`x`というプロパティを持っていなければいけない しかしこのような条件を満たしていることが分かっていてもコンパイラが推論出来ておらずエラーになることがあります。 そのような時は以下のようなCast型を定義して使いましょう。 これはTはPを継承している時は分かっている時にCast<T, P>と書いて使います。 type Cast<T, P> = T extends P ? T : P; 例です。
2019/04/12
この記事はTS3.4.3で動作確認をしています。 ハイパー演算子とは hyper(1,a,b)=a+b hyper(2,a,b)=a*b hyper(3,a,b)=a^b ︙ のような演算子です(雑) 詳しくはWikipediaを見て下さい。 定義だけ貼っておきます。 hyper(1,a,b)=a+b hyper(_,a,1)=a hyper(i,a,1)=hyper(i-1,a,hyper(i,a,b-1)) 型レベルタプル操作 型レベルのタプル操作を行うので以下の記事を読んでおくといいかもしれません。 TypeScript 3.0のExtracting and spreading parameter lists with tuplesで遊ぼう ちなみに今回は上の記事の型レベルタプル操作などをまとめた自作ライブラリtypeparkを使いますが機能は上の記事の通りです。 再帰制限回避テク FやGが複雑な関数だと以下のような書き方をするとコンパイルエラーが発生することがあります。 type Hoge<T>=F<Cast<G<T
2019/04/11
TypeScriptのランタイム型チェック TypeScriptにはランタイム型チェック機能がありません。 次のようなコードも正常にコンパイルされエラーが発生することなく動作します。 const x: string = JSON.parse("1"); これはパフォーマンスなどとのトレードオフなので仕方ないのですが、部分的に動的な型チェックをしたいときもあります。 このような時の解決策としてio-tsを紹介します。 io-tsのメリット JSON Schemaなどは型とスキーマを2つ書く必要があり大変です。 また大変なだけでなく型とスキーマが異なるといったバグを型システムでチェックすることが出来ません。 コードジェネレーターを使うことで解決できますが、TypeScript上で完結しないのでめんどくさいです。 このような問題はio-tsを使うことで解決します。 ただし再帰型については型推論の関係で型とスキーマを2回書く必要がありますが、型チェックでスキーマと型が違っていればコンパイルエラーが発生します。 基本的な使い方 import
2018/10/02
Extracting and spreading parameter lists with tuples TS3.0で追加されたタプル型をより強力に扱うための機能です。 型パラメーターとして受け取ったタプルを展開したり出来ます。 基本的な構文は解説しないので公式ブログあたりを見ておいて下さい。 参考 Tuples in rest parameters and spread expressions #24897 このPRで紹介されているものを主に解説していきます。 注意 TypeScript3.0.xにはバグがありコンパイラやエディタ(正格にはtsserver)がクラッシュすることがあるのでTypeScript3.1.xを使って下さい。 前提知識 TSの基本的な型システムの知識宣言的なリスト操作(Haskellなどでやるあれ) 用語 この記事では、type F<T>=...;を関数のように扱うので、Fを関数、Tを引数、タプル型をリスト、type V=...;を値と表現します。 紹介 Head リストの先頭の要素を返す基本的な関数で
2018/09/18
はじめに TypeScript(TS)には高カインド型(HKT)がありません。一応提案がありますが… しかし様々な機能を組み合わせればHKTを実現することが出来るのでそれの方法と解説を行います。 この記事ではHKTとは何かなどといった解説は行いません。表記は*->*のような表記を使います。 またfp-tsというライブラリを参考にしています。 使う機能 interfaceのマージ(Declaration Merging) TypeScriptでは同名のinterfaceを複数定義出来ます。 そしてこれらは自動的にマージされます。 例えば次の2つの宣言は同等です。 export interface Hoge { x: number; } export interface Hoge { y: number; } export interface Hoge { x: number; y: number; } そしてこの機能は別ファイルや別モジュールで既に定義されているinterfaceを拡張する事も出来ます
2018/09/10
やり方 準備 export type TypeEq<A, B> = (<T>() => T extends A ? 1 : 2) extends (< T >() => T extends B ? 1 : 2) ? true : false export function assertType<_T extends true>() {} export function assertNotType<_T extends false>() {} 色々複雑になっていますが、これは any や union、never などに対応するためです。 ここらへんの型は少し特殊なため、このようにしないと正常にテスト出来ません。 テストの書き方 assertType<TypeEq<1, 1>>() assertNotType<TypeEq<1, 2>>() テストが正しくなければコンパイルエラーが発生します。 例 import { TypeEq, assertType, assertNotType } from "./test" asse