コンピュテーション式で"はちみーのうた"
コンピュテーション式でキーワード引数 - ぐるぐる~ や カスタムオペレーションの呼び出し順序を制御する - Qiita をみていたら久々にコンピュテーション式で遊びたくなったのでひとネタ供養。
今回のネタは状態遷移を書けると噂の”はちみーのうた”です。 歌詞通りにキーワードを呼び出さないとコンパイルエラーになるはず、きっと。 まぁ多少の妥協があります。
type GotoHachimi = interface end type GotoAshi = interface end type Hachimi = Hachimi with override _.ToString() = "はちみー" interface GotoHachimi type Hachimi<'T when 'T :> GotoHachimi> = Hachimi of 'T with override this.ToString() = match this with | Hachimi t -> sprintf $"{t}はちみー" interface GotoHachimi type Nameru<'T when 'T :> GotoHachimi> = Nameru of 'T with override this.ToString() = match this with | Nameru t -> sprintf $"{t}をなめると" interface GotoAshi interface GotoHachimi type Ashi<'T when 'T :> GotoAshi> = Ashi of 'T with override this.ToString() = match this with | Ashi t -> sprintf $"{t}あしがー" interface GotoAshi type Hayakunaru<'T when 'T :> GotoAshi> = Hayakunaru of 'T with override this.ToString() = match this with | Hayakunaru t -> sprintf $"{t}はやくーなる" interface GotoHachimi type Lyrics = Nameru<Hachimi<Hachimi<Hachimi<Hachimi< Nameru<Hachimi<Hachimi<Hachimi<Hachimi< Hayakunaru<Ashi<Ashi<Ashi<Nameru<Hachimi<Hachimi<Hachimi<Hachimi>>>>>>>> >>>>> >>>>> type HachimiSongBuilder () = member _.Yield(()) = () // 右辺が `Hachimi` だけだと `'T -> Hachimi<'T>` を返してしまうので、 `Hachimi.Hachimi` で固定できるようにしておく [<CustomOperation("はちみー")>] member _.Hachimi(()) = Hachimi.Hachimi [<CustomOperation("はちみー")>] member _.Hachimi(x: #GotoHachimi) = Hachimi(x) [<CustomOperation("をなめると")>] member _.Nameru(x: Hachimi<Hachimi<Hachimi<#GotoHachimi>>>) = Nameru(x) [<CustomOperation("あしがー")>] member _.Ashi(x: #GotoAshi) = Ashi(x) [<CustomOperation("はやくーなる")>] member _.Hayakunaru(x: Ashi<Ashi<Ashi<Nameru<_>>>>) = Hayakunaru(x) member _.Run(song: Lyrics) = printfn $"{song}" let はちみーのうた = HachimiSongBuilder() はちみーのうた { はちみー; はちみー; はちみー はちみー; をなめると あしがー; あしがー; あしがー はやくーなる はちみー; はちみー; はちみー はちみー; をなめると はちみー; はちみー; はちみー はちみー; をなめると }
出力:
はちみーはちみーはちみーはちみーをなめるとあしがーあしがーあしがーはやくーなるはちみーはちみーはちみーはちみーをなめるとはちみーはちみーはちみーはちみーをなめると
- 初回はかならず”はちみー”が来てほしいので単発の
Hachimi
が来るようにYield
とHachimi
メソッドを用意 - カスタムパラメータはoverloadが可能
- 繰り返しを雑に省略定義するために interface を使用
はちみー
を 4回繰り返さないとをなめると
に移動できないように引数の型を調整あしがー
3回も同じ方法
Run
メソッドの引数をLyrics
型に限定することで、歌詞通りなことを保証する- 型パラメータに制約をつけているけど、なくてもたぶん問題ない
久しぶりの記事がこんなのでいいのだろうか :thinking_face: