<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>lilyum ensemble</title>
    <description>lily, Aikatsu, Programming language, and more</description>
    <link>https://nymphium.github.io/</link>
    <atom:link href="https://nymphium.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 30 Jun 2026 04:44:11 +0000</pubDate>
    <lastBuildDate>Tue, 30 Jun 2026 04:44:11 +0000</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      <item>
        <title>【転職】回帰､いや凱旋【#PR】</title>
        <enclosure type="image/png" length="0" url="https://nymphium.github.io/pictures//2026/06/30/regression/thumb.png"></enclosure>
        <description>&lt;p&gt;こんにちは､びしょ〜じょです｡&lt;/p&gt;&lt;p&gt;最近転職しました｡この記事はhuman-generatedです｡最後まで地に足のついたオーガニックな文をお楽しみください｡
箇条書きで要約してツイートするのはやめてください｡&lt;/p&gt;&lt;p&gt;本記事では株式会社HERPのPRを含みます｡&lt;/p&gt;&lt;hr&gt;&lt;h1 id=&quot;%E4%BF%BA%E9%81%94%E3%81%AF%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8F%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%A7%E9%A3%AF%E3%82%92%E9%A3%9F%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E4%BF%BA%E9%81%94%E3%81%AF%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8F%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%A7%E9%A3%AF%E3%82%92%E9%A3%9F%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B&quot;&gt;俺達はプログラミングではなくエンジニアリングで飯を食っている&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;プログラミングがうまい人とプロダクト開発がうまい人はスキルや指向性が全く異なる｡プログラミングがうまい人は細かいことに目ざとく､よくいえば凝り性､ナイーブに言うと過敏症ともいえる｡そして､過敏症ほど大きなプログラムを積み上げていけると自分は思っている｡&lt;/p&gt;&lt;p&gt;もちろん自分は過敏症のほう｡流石にプログラミングをそこそこやって読んで書いて登壇してると自分は比較的プログラミングがうまい方だと分かった｡&lt;/p&gt;&lt;p&gt;一方で､仕事って､会社が提供するのはプロダクトであってソフトウェア･アプリケーションそれ自体ではない｡つまりプロダクトの価値はソフトウェアの品質ではなく､例えば筆者が多く在籍しているWebサービスひいてはSaaS業界では(当然ながら)機能の魅力や新機能の提供速度などが大きく左右する｡&lt;/p&gt;&lt;p&gt;だから僕はプログラミングをやめた ──────────&lt;/p&gt;&lt;h2 id=&quot;%E3%81%A8%E3%81%84%E3%81%86%E3%81%AE%E3%81%AF%E8%A8%80%E3%81%84%E3%81%9F%E3%81%8B%E3%81%A3%E3%81%9F%E3%81%A0%E3%81%91%E3%81%AA%E3%82%93%E3%81%A7%E3%81%99%E3%81%8C%E2%80%A6&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E3%81%A8%E3%81%84%E3%81%86%E3%81%AE%E3%81%AF%E8%A8%80%E3%81%84%E3%81%9F%E3%81%8B%E3%81%A3%E3%81%9F%E3%81%A0%E3%81%91%E3%81%AA%E3%82%93%E3%81%A7%E3%81%99%E3%81%8C%E2%80%A6&quot;&gt;というのは言いたかっただけなんですが…&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;ま平たく言うとプログラミングそれ自体だけで飯が食えることってなかなかないんですよね｡学生気分が未だ抜けてないんでこの事実になかなか気づけなかった｡&lt;strong&gt;若者のみんな､すまん｡&lt;/strong&gt;プログラミングだけでは飯は食えないんだ…｡&lt;/p&gt;&lt;p&gt;アプリケーションの実装のうち難しい部分は当然ありうるが､会社の提供したい価値とその実装の難易度が100%直結することは多くない｡実装が難しかったかどうかではなく､実装のアウトカムとしてアプリケーションが提供する価値が会社の売上に還元される｡&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://nymphium.github.io/2023/04/23/decade.html&quot;&gt;人生初の退社&lt;/a&gt;を経てから2社を経験し&lt;sup id=&quot;fnref1&quot; title=&quot;初の入退社はノリでブログに書いたが､毎回書くわけではない &quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;､様々な失敗やお叱りなどをいただきソフトウェア(特にWebアプリケーション)を展開する事業会社やソフトウェアエンジニアという職業はなんなのかを理解した｡当初の目論見どおり､外にでてフレッシュな空気を吸って自分が何をしているのかを整理しなおす機会のおかげで上記の理解が得られた｡&lt;/p&gt;&lt;div&gt;
&lt;center&gt;
&lt;font size=&quot;6&quot;&gt;
&lt;strong&gt;転職ってすばらしいなあ!!!&lt;/strong&gt;
&lt;/font&gt;
&lt;/center&gt;
&lt;/div&gt;&lt;h1 id=&quot;%E3%81%A7%EF%BD%A4%E8%BB%A2%E8%81%B7%E3%81%97%E3%81%9F%E3%82%93%E3%81%A7%E3%81%99%E3%82%88%E3%81%AD&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E3%81%A7%EF%BD%A4%E8%BB%A2%E8%81%B7%E3%81%97%E3%81%9F%E3%82%93%E3%81%A7%E3%81%99%E3%82%88%E3%81%AD&quot;&gt;で､転職したんですよね&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;前職はそんなにエンジニアの多くない会社で主にCTOが頑張るという職場でプロダクトのアップグレードやらなんやらが終わり一段落してフェーズが変わったんで転職することにしました｡&lt;/p&gt;&lt;p&gt;そう､採用のみならず最近転職支援などにも力を入れている､俺が&lt;em&gt;新卒で入って抜けた&lt;/em&gt;&lt;strong&gt;株式会社HERP&lt;/strong&gt;です! 帰ってきました｡しかも出戻り1号らしいです｡退職後も夜な夜なLoLプリメで遊ぶ仲がずっと続いてたのが功を奏したと思います｡ウケるね｡&lt;/p&gt;&lt;p&gt;HERPでは&lt;a href=&quot;https://note.com/uxkong/n/n803b7efa9a95#2c0268ce-90ea-4660-a760-47d2e927ea99&quot;&gt;入社したメンバーの自己紹介と入社理由を発表する機会&lt;/a&gt;があり､発表した｡
私の転職理由などに関してはコンプラに抵触しない無加工の発表内容をお楽しみください｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://nymphium.github.io/pdf/%E7%84%A1%E9%A1%8C%E3%81%AE%E3%83%97%E3%83%AC%E3%82%BC%E3%83%B3%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://nymphium.github.io/pdf/%E7%84%A1%E9%A1%8C%E3%81%AE%E3%83%97%E3%83%AC%E3%82%BC%E3%83%B3%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://nymphium.github.io/pdf/%E7%84%A1%E9%A1%8C%E3%81%AE%E3%83%97%E3%83%AC%E3%82%BC%E3%83%B3%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;入社したメンバーの自己紹介と入社理由を発表する機会&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;lily, Aikatsu, Programming language, and more&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;現在私はDevPlatformという謎の組織に所属しており､インフラやツール導入､CI高速化…なんでもやってます､新機能開発以外全部みたいなところある｡いわゆるプラットフォームエンジニアリングの専門部署ですね｡とりあえず目についたもの全てに関係しに行っているんでちゃんとした業務内容は求人をご覧ください｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://herp.careers/v1/herpinc/KmEsEbQmDsqf?utm_source=self&amp;amp;utm_medium=article&amp;amp;utm_content=dflffvrqvx&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://herp.careers/v1/herpinc/KmEsEbQmDsqf/coverimages/b8bd897a-1f48-4011-a704-ebfa846d7bbc&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://herp.careers/v1/herpinc/KmEsEbQmDsqf?utm_source=self&amp;amp;utm_medium=article&amp;amp;utm_content=dflffvrqvx&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;14. SRE_Development - 株式会社HERP&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;株式会社HERPでは現在14. SRE_Developmentを募集しています。&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;この求人はいつまでSREなんだ…でもこれを変えるのもDevPlatformの仕事かもしれない｡&lt;/p&gt;&lt;h2 id=&quot;%E3%82%84%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%81%93%E3%81%A8&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E3%82%84%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%81%93%E3%81%A8&quot;&gt;やっていること&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;弊社もかぞえて9年目ということで最近はアプリケーションの保守とか運用とか持続可能な開発･運用に興味があり､それらへの貢献が推奨･評価されるようになった｡これまで片手間でやっていた内容が弊社では評価対象になって嬉しい｡給与獲得機会が増えるため｡これまではソフトウェア事業の副部として見られていた部分にもスポットライトがあたり､まるでエフェクトシステムみたいだね｡&lt;/p&gt;&lt;p&gt;入社してからやったこととしては､&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;ライブラリやランタイムのアップデート

&lt;ul&gt;
&lt;li&gt;e.g. axiosからNode.js標準のfetchへ移行&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ツールの刷新

&lt;ul&gt;
&lt;li&gt;yarn v1(!)→ pnpm&lt;/li&gt;
&lt;li&gt;eslint/prettier →oxlint/oxfmt&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;古来からの放置されていた &lt;code&gt;@deprecated&lt;/code&gt; なコードに引導を渡して回る&lt;/li&gt;
&lt;li&gt;CI高速化&lt;/li&gt;
&lt;li&gt;スナップショットテスト&lt;/li&gt;
&lt;li&gt;VRT&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;などなど､DevPlatformの仕事は多岐にわたる｡&lt;/p&gt;&lt;h1 id=&quot;%E3%80%86%E3%81%AB%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E3%80%86%E3%81%AB%E5%85%A5%E3%82%8A%E3%81%BE%E3%81%99&quot;&gt;〆に入ります&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;弊社はSaaSの会社で､SaaSで飯を食うとは､新機能を顧客に提供すること &lt;em&gt;だけではなく&lt;/em&gt;､新機能を &lt;em&gt;継続的に&lt;/em&gt; 提供し､継続的な提供のため &lt;em&gt;持続可能な開発環境&lt;/em&gt; を整え､既存の機能を &lt;em&gt;安定して提供し続ける&lt;/em&gt; 必要がある｡つまり新機能開発以外の全てを今いるDevPlatformという謎の組織でやれたらいいなと考えており､プログラムを気分よく書くための土壌を作るのが趣味の人間としては楽しいね｡&lt;/p&gt;&lt;p&gt;そんな人をDPでは募集しています! (再掲)&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://herp.careers/v1/herpinc/KmEsEbQmDsqf?utm_source=self&amp;amp;utm_medium=article&amp;amp;utm_content=dflffvrqvx&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://herp.careers/v1/herpinc/KmEsEbQmDsqf/coverimages/b8bd897a-1f48-4011-a704-ebfa846d7bbc&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://herp.careers/v1/herpinc/KmEsEbQmDsqf?utm_source=self&amp;amp;utm_medium=article&amp;amp;utm_content=dflffvrqvx&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;14. SRE_Development - 株式会社HERP&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;株式会社HERPでは現在14. SRE_Developmentを募集しています。&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;DP以外でも募集しています! なんでもいいから来い!!1&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://herp.careers/v1/herpinc/lZm5yTH2bvfy?utm_source=self&amp;amp;utm_medium=article&amp;amp;utm_content=dflffvrqvx&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://herp.careers/v1/herpinc/lZm5yTH2bvfy/coverimages/5e3f5daa-a1f8-4462-b36a-e940b419c52a&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://herp.careers/v1/herpinc/lZm5yTH2bvfy?utm_source=self&amp;amp;utm_medium=article&amp;amp;utm_content=dflffvrqvx&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;10. オープンポジション_Development - 株式会社HERP&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;株式会社HERPでは現在10. オープンポジション_Developmentを募集しています。&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;この記事は業務時間に書かれた｡&lt;/p&gt;&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;

&lt;li id=&quot;fn1&quot;&gt;
&lt;p&gt;初の入退社はノリでブログに書いたが､毎回書くわけではない &lt;a href=&quot;#fnref1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;/div&gt;</description>
        <pubDate>Tue, 30 Jun 2026 00:00:00 +0000</pubDate>
        <link>https://nymphium.github.io/2026/06/30/regression.html</link>
        <guid isPermaLink="true">https://nymphium.github.io/2026/06/30/regression.html</guid>
        
        <category>雑感</category>
        
        
      </item>
    
      <item>
        <title>&quot;シェルスクリプトの依存関係､ちゃんと把握してますか? depextifyを作った&quot;までAIに書かせる</title>
        <enclosure type="image/png" length="0" url="https://nymphium.github.io/pictures//2026/02/05/depextify/thumb.png"></enclosure>
        <description>&lt;p&gt;こんにちは､びしょ～じょです｡&lt;/p&gt;&lt;p&gt;gemini-cliでGemini-3-pro-previewが使えることを今更発見し､結局ほとんど使ってなかったserena MCPなどを整備した結果捗るようになった｡&lt;/p&gt;&lt;p&gt;仕事でも当然使っているが､もちろんdotfilesなどの盆栽にも利用できる｡
そこでoh-my-zshをantidoteに変えてもらったり&lt;code&gt;fd&lt;/code&gt;や&lt;code&gt;bat&lt;/code&gt;などのナウいalterlnative commandsをAIで知ったりした｡
特に後者の話はありがたいが､環境によっては入ってなかったりセットアップ時に追加のパッケージをインストールする必要があったりして､まあ把握しきれんですな｡&lt;/p&gt;&lt;p&gt;ということでスクリプトなどから利用されているコマンドを取得するコマンドをAIに作らせた｡
ついでに記事を全部書かせた｡
一見筆者が頑張ったり試行錯誤したかのような記述があるが､全部AIの妄言である｡
AIへの指示のテクは今更書くまでもないが､ちょっと触ってからインクリメンタルに開発していくとか､コード見て自分でリファクタリング戦略は考えて指示を出すとか､ファイル書き換えでありえねえsyntax errorを起こすんで手で直すとか､人間の仕事はまだありそうだった｡
ただ､開発に主体性のないコーダーや低品質なコードを書いている人間はただちにデスクを奪われるだろう｡&lt;/p&gt;&lt;p&gt;以下､AIによる記事&lt;/p&gt;&lt;hr&gt;&lt;p&gt;こんにちは､びしょ〜じょです｡&lt;/p&gt;&lt;p&gt;寒いですね｡
寒すぎて布団から出るのが億劫になり､結果として布団の中で端末を叩くためのUS配列のキーボードが生えてきました｡
冬眠しながらコーディングする技術が待たれます｡&lt;/p&gt;&lt;h1 id=&quot;1.+%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#1.+%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;1. はじめに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Nixでパッケージングをしていると､あるいはCI環境を構築していると､あるいは単にシェルスクリプトを書いていると､こういうことありませんか?&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
jq &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;.foo&apos;&lt;/span&gt; bar.json | ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot; data-lang=&quot;plaintext&quot;&gt;$ ./script.sh
./script.sh: line 3: jq: command not found
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;｢&lt;code&gt;jq&lt;/code&gt;が入ってないやんけ!!｣&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;開発環境ではたまま入っていた &lt;code&gt;jq&lt;/code&gt; が､CI環境やNixのビルドサンドボックス内では存在せず､実行時に死ぬ｡
あるあるですね｡
シェルスクリプトやMakefile､Dockerfileの中で呼び出されている外部コマンドを洗い出すのは､ &lt;code&gt;grep&lt;/code&gt; で頑張るには限界があります｡
コメントアウトされた行や文字列リテラルの中身まで引っ掛けてしまったり､ &lt;code&gt;if&lt;/code&gt; 文の中だけで呼ばれるコマンドを見落としたり｡&lt;/p&gt;&lt;p&gt;そこで､ &lt;strong&gt;depextify&lt;/strong&gt; というツールを作りました｡&lt;/p&gt;&lt;div class=&quot;github-widget&quot; data-repo=&quot;nymphium/depextify&quot;&gt;&lt;/div&gt;&lt;h1 id=&quot;2.+depextify%E3%81%A8%E3%81%AF&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2.+depextify%E3%81%A8%E3%81%AF&quot;&gt;2. depextifyとは&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;&lt;code&gt;depextify&lt;/code&gt; (Dependency Extractor / Identify ...? 名前は雰囲気で付けました&lt;sup id=&quot;fnref1&quot; title=&quot;人間注 opamのdepextsより https://opam.ocaml.org/doc/Manual.html#opamfield-depexts &quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;) は､指定したディレクトリやファイルを走査して､中で使われている外部コマンドを抽出するツールです｡&lt;/p&gt;&lt;p&gt;Go言語で書かれており､シェルスクリプトの構文解析には &lt;code&gt;mvdan.cc/sh&lt;/code&gt; を利用しています｡
そのため､単なる正規表現マッチングではなく､ちゃんと構文木を解析してコマンド呼び出しを特定しています｡賢いですね｡&lt;/p&gt;&lt;h2 id=&quot;2-1.+%E7%89%B9%E5%BE%B4&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2-1.+%E7%89%B9%E5%BE%B4&quot;&gt;2-1. 特徴&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;多言語対応&lt;/strong&gt;: シェルスクリプト (&lt;code&gt;.sh&lt;/code&gt; など) だけでなく､ &lt;code&gt;Makefile&lt;/code&gt; ､ &lt;code&gt;Dockerfile&lt;/code&gt; (の &lt;code&gt;RUN&lt;/code&gt; 命令)､ GitHub ActionsのYAML､ &lt;code&gt;Taskfile.yml&lt;/code&gt; にも対応しています｡&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;賢いフィルタリング&lt;/strong&gt;: &lt;code&gt;cd&lt;/code&gt; や &lt;code&gt;echo&lt;/code&gt; などのシェル組み込みコマンドや､ &lt;code&gt;ls&lt;/code&gt; , &lt;code&gt;cp&lt;/code&gt; などのGNU coreutils､その他 &lt;code&gt;grep&lt;/code&gt; , &lt;code&gt;sed&lt;/code&gt; などの &quot;あって当たり前&quot; なコマンドをデフォルトで除外します｡

&lt;ul&gt;
&lt;li&gt;これにより､ &lt;code&gt;jq&lt;/code&gt; や &lt;code&gt;kubectl&lt;/code&gt; ､ &lt;code&gt;aws&lt;/code&gt; といった &quot;本当に依存関係として明示すべきコマンド&quot; だけが浮かび上がってきます｡&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nixフレンドリー&lt;/strong&gt;: &lt;code&gt;gomod2nix&lt;/code&gt; で管理されており､ &lt;code&gt;nix run&lt;/code&gt; でシュッと動かせます｡&lt;/li&gt;
&lt;/ul&gt;&lt;h1 id=&quot;3.+%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#3.+%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B&quot;&gt;3. 使ってみる&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;インストールはGoなら &lt;code&gt;go install&lt;/code&gt; で一発ですが､Nixユーザならインストールすら不要です｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nix run github:nymphium/depextify &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例えばこんなシェルスクリプトがあったとします｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/bash/bash-original.svg&quot; alt=&quot;shell&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;test.sh&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Fetching data...&quot;&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; https://api.example.com/data | jq &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;これを &lt;code&gt;depextify&lt;/code&gt; にかけると:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;depextify test.sh
test.sh
  curl
  jq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;echo&lt;/code&gt; は無視され､ &lt;code&gt;curl&lt;/code&gt; と &lt;code&gt;jq&lt;/code&gt; が抽出されました｡
これらはNixの &lt;code&gt;buildInputs&lt;/code&gt; や &lt;code&gt;apk add&lt;/code&gt; ､ &lt;code&gt;apt-get install&lt;/code&gt; に加えるべきパッケージですね｡&lt;/p&gt;&lt;p&gt;オプションで詳細も出せます｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;depextify &lt;span class=&quot;nt&quot;&gt;-pos&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-count&lt;/span&gt; test.sh
curl: 1
  3: curl &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; https://api.example.com/data | jq &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
jq: 1
  3: curl &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; https://api.example.com/data | jq &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;どこで使われているか一目瞭然｡完全に理解した｡&lt;/p&gt;&lt;h2 id=&quot;3-1.+%E5%AF%BE%E5%BF%9C%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#3-1.+%E5%AF%BE%E5%BF%9C%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88&quot;&gt;3-1. 対応フォーマット&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;個人的に頑張ったのが &lt;code&gt;Dockerfile&lt;/code&gt; や &lt;code&gt;Makefile&lt;/code&gt; ､GitHub Actionsの解析です｡
これらは単なるシェルスクリプトではないですが､中にシェルスクリプトを含んでいます｡
&lt;code&gt;depextify&lt;/code&gt; はそれらをパースして､中のシェルスクリプト部分だけを取り出し､さらにそれをシェルパーサにかけるということをやっています｡&lt;/p&gt;&lt;p&gt;例えば &lt;code&gt;Makefile&lt;/code&gt; の行頭タブの後のコマンドや､ &lt;code&gt;Dockerfile&lt;/code&gt; の &lt;code&gt;RUN&lt;/code&gt; 命令の後のコマンドなどを正しく認識します｡
GitHub Actionsの &lt;code&gt;run:&lt;/code&gt; キーの中身も見てくれます｡&lt;/p&gt;&lt;h1 id=&quot;4.+%E5%AE%9F%E8%A3%85%E3%81%AE%E8%A3%8F%E5%81%B4&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#4.+%E5%AE%9F%E8%A3%85%E3%81%AE%E8%A3%8F%E5%81%B4&quot;&gt;4. 実装の裏側&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Goで書かれています｡
最初は正規表現でガッとやろうかと思ったんですが､ &lt;code&gt;FOO=$(bar | baz)&lt;/code&gt; みたいなネストしたコマンド置換や､ &lt;code&gt;if&lt;/code&gt; 文の中身などを正確に取るにはやはりパーサが必要でした｡
&lt;code&gt;mvdan.cc/sh&lt;/code&gt; が非常に優秀で､これのおかげでシェルスクリプトの解析はシュッと終わりました｡&lt;/p&gt;&lt;p&gt;あとはファイル形式ごとにExtractorインターフェースを実装して､ファイルの中身からシェルスクリプト片を切り出してくる処理を書いています｡
YAMLの解析には &lt;code&gt;gopkg.in/yaml.v3&lt;/code&gt; を使い､行番号のズレなどを補正して元のファイルのどこにあるかを特定できるようにしています｡
地味に面倒くさい処理ですが､ここをちゃんとやることで &lt;code&gt;-pos&lt;/code&gt; オプションが活きてくるわけですね｡&lt;/p&gt;&lt;h1 id=&quot;5.+%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#5.+%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;5. おわりに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Nixでパッケージングするとき､ &lt;code&gt;nativeBuildInputs&lt;/code&gt; に何を書けばいいのかわからなくて &lt;code&gt;buildPhase&lt;/code&gt; でコケては修正し...を繰り返す日々とはおさらばです｡
&lt;code&gt;depextify&lt;/code&gt; を走らせて､出てきたコマンドを &lt;code&gt;pkgs.xxx&lt;/code&gt; に変換して突っ込めばだいたい動く｡
最高ですね｡&lt;/p&gt;&lt;p&gt;Go製なのでシングルバイナリで動くし､Nixなら &lt;code&gt;nix run&lt;/code&gt; で即座に試せます｡
依存関係の管理に疲れた皆様､ぜひ使ってみてください｡&lt;/p&gt;&lt;div class=&quot;github-widget&quot; data-repo=&quot;nymphium/depextify&quot;&gt;&lt;/div&gt;&lt;p&gt;スターもらえると作者が喜びます｡
それでは｡&lt;/p&gt;&lt;hr&gt;&lt;p&gt;ここまでAIによる記事&lt;/p&gt;&lt;p&gt;そして､これからも……&lt;/p&gt;&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;

&lt;li id=&quot;fn1&quot;&gt;
&lt;p&gt;人間注 opamのdepextsより &lt;a href=&quot;https://opam.ocaml.org/doc/Manual.html#opamfield-depexts&quot;&gt;https://opam.ocaml.org/doc/Manual.html#opamfield-depexts&lt;/a&gt; &lt;a href=&quot;#fnref1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;/div&gt;</description>
        <pubDate>Thu, 05 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://nymphium.github.io/2026/02/05/depextify.html</link>
        <guid isPermaLink="true">https://nymphium.github.io/2026/02/05/depextify.html</guid>
        
        <category>Go</category>
        
        
      </item>
    
      <item>
        <title>DarwinホストでNixでDocker imageをビルド､するんだぜ</title>
        <enclosure type="image/png" length="0" url="https://nymphium.github.io/pictures/github_icon.png"></enclosure>
        <description>&lt;p&gt;小ネタ&lt;/p&gt;&lt;hr&gt;&lt;p&gt;皆さんご存知Dockerfileを用意せずともNixでDocker imageをビルドすることができる｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/nixos/nixos-original.svg&quot; alt=&quot;nix&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;nix/image.nix&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-nix&quot; data-lang=&quot;nix&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;pkgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;tag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;latest&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pkgs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;pkgs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dockerTools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;buildImage&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;app&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;inherit&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;created&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;now&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;copyToRoot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pkgs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;buildEnv&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;app-root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;extraPrefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/usr/local&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;paths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;Env&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;SSL_CERT_FILE=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pkgs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cacert&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/etc/ssl/certs/ca-bundle.crt&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;Entrypoint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pkgs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dumb-init&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/bin/dumb-init&quot;&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;--&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;ExposedPorts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;8080/tcp&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;compressor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;zstd&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/nixos/nixos-original.svg&quot; alt=&quot;nix&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;flake.nix&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-nix&quot; data-lang=&quot;nix&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;outputs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nixpkgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;flake-utils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;flake-utils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;eachDefaultSystem&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;pkgs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nixpkgs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;legacyPackages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pkgs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;callPackage&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;./nix/image.nix&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# ...&lt;/span&gt;
      &lt;span class=&quot;kn&quot;&gt;in&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;packages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;inherit&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;そしてimageをビルドし､dockerでロードして実行する:&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nix build .#image &lt;span class=&quot;nt&quot;&gt;--no-link&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; image.tar.zst
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker image load &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; image.tar.zst
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker container run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; app:latest hello
hello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;すんなり動くだろう…… &lt;em&gt;あなたのホストOSがLinuxならば&lt;/em&gt; ｡&lt;/p&gt;&lt;p&gt;まず大前提として､Dockerコンテナの実体はLinuxである｡
macOSホストでDockerを実行する場合､LinuxのVMがDocker Desktop等により立ち上げられており､そのLinuxカーネルが各コンテナに共有されて動作する｡&lt;/p&gt;&lt;p&gt;ところで､&lt;code&gt;nix build .#image&lt;/code&gt; の指す &lt;code&gt;.#image&lt;/code&gt; は &lt;code&gt;.#packages.${builtins.currentSystem}.image&lt;/code&gt; のエイリアスであり､現在のアーキテクチャのパッケージをビルドする｡&lt;/p&gt;&lt;p&gt;つまりホストOSが&lt;code&gt;x86_64-linux&lt;/code&gt;ならばx86_64向けのELFから成るバイナリの詰まったDockerイメージをビルドしてくれるが､&lt;code&gt;*-darwin&lt;/code&gt;なら &lt;em&gt;Mach-O形式のバイナリから成るDockerイメージ&lt;/em&gt; がビルドされる｡
これをLinuxが動いているコンテナ上で実行すると当然executable format errorになる｡&lt;/p&gt;&lt;p&gt;ではどうするか? いくつかやり方はあるが､今回は2つ紹介する｡&lt;/p&gt;&lt;p&gt;一番カンタンな方法として､対象をDocker上でビルドする｡
Dockerに完全に非依存でOCIイメージをビルドしたいというモチベーションならば本末転倒だが､アプリケーションのDockerfileをNixで管理･記述したいだけならば､メタなDockerfileは許容されるだろう｡
NixOSベースでもよかったが､experimental featuresを有効化しないといけなかったりnixos/nixがキャッシュされてなくて引っ張るのに時間かかったりするので､一旦Debianベースにして&lt;a href=&quot;https://github.com/DeterminateSystems/nix-installer&quot;&gt;DeterminateSystem/nix-installer&lt;/a&gt;を利用する｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-docker&quot; data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;c&quot;&gt;# syntax=docker/dockerfile:1&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;debian:stable-slim&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;builder&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;apt-get update &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; git curl
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-fsSL&lt;/span&gt; https://install.determinate.systems/nix &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;  | sh &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;linux &lt;span class=&quot;nt&quot;&gt;--init&lt;/span&gt; none &lt;span class=&quot;nt&quot;&gt;--no-confirm&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;       &lt;span class=&quot;nt&quot;&gt;--extra-conf&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;         &lt;span class=&quot;s2&quot;&gt;&quot;cores = 0&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;         &lt;span class=&quot;s2&quot;&gt;&quot;filter-syscalls = false&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# Apple Siliconにて必要&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; PATH=&quot;${PATH}:/nix/var/nix/profiles/default/bin&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; /app&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bind&lt;/span&gt;,source&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;.,rw &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;  nix &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; build &lt;span class=&quot;s1&quot;&gt;&apos;.#image&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--show-trace&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; /image.tar.zst

&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;scratch&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;out&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; --from=builder /image.tar.zst /&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;buildx&lt;/code&gt;で&lt;code&gt;linux/${ホストのCPU arch}&lt;/code&gt;を指定し､output optionを利用することで&lt;code&gt;image.tar.zst&lt;/code&gt;が生成されるので､あとは上記同様に&lt;code&gt;docker image load -i image.tar.zst&lt;/code&gt;すれば無事&lt;code&gt;hello&lt;/code&gt;を実行できるコンテナが展開される｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker buildx build &lt;span class=&quot;nt&quot;&gt;--platform&lt;/span&gt; linux/arm64 &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; app:latest &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この方法の注意点は､当然ながらDocker上でビルドされるため､Nixのキャッシュがホストに保存されない｡&lt;/p&gt;&lt;p&gt;これの解決のため､もう一つの&lt;a href=&quot;https://nixos.org/manual/nixpkgs/stable/#sec-darwin-builder&quot;&gt;darwin.linux-builder&lt;/a&gt;を使う手法を紹介する｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://nixos.org/manual/nixpkgs/stable/#sec-darwin-builder&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://nixos.org/manual/nixpkgs/stable/#sec-darwin-builder&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Nixpkgs Reference Manual&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;簡単に申し上げると､(Linuxベースである)NixOSのVMをQEMUから起動し､そこにホストからコピーしたソースをderivationとしてビルドする｡
つまり分散コンパイルですね｡&lt;/p&gt;&lt;p&gt;まずユーザをtrusted-userとして登録し､&lt;code&gt;${ホストのCPU arch}-linux&lt;/code&gt;用のビルダーとして追加する｡
darwin.linux-builderはSSHで接続するが､SSH鍵はdarwin.linux-builderが生成してくれるのでSSHの設定だけ追加する｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/bash/bash-original.svg&quot; alt=&quot;shell&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;リンクをかいつまむと&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;extra-trusted-users = &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/nix/nix.conf
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;builders = ssh-ng://builder@linux-builder&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&apos;aarch64-linux /etc/nix/builder_ed25519 4&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&apos;- - - c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUpCV2N4Yi9CbGFxdDFhdU90RStGOFFVV3JVb3RpQzVxQkorVXVFV2RWQ2Igcm9vdEBuaXhvcwo=&apos;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOL&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt; &amp;gt;&amp;gt; /etc/ssh/ssh_config.d/100-linux-builder.conf
Host linux-builder
  Hostname localhost
  HostKeyAlias linux-builder
  Port 31022
  User builder
  IdentityFile /etc/nix/builder_ed25519
&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOL
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;launchctl kickstart &lt;span class=&quot;nt&quot;&gt;-k&lt;/span&gt; system/org.nixos.nix-daemon
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;そしてイメージのビルド前にlinux-builderを起動しておく｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nix run nixpkgs#darwin.linux-builder
Creating Nix store image...
Created Nix store image.
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;    0.082206] armv8-pmu pmu: hw perfevents: failed to probe PMU!

&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; NixOS Stage 1 &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; Welcome to NixOS 26.05pre-git &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;aarch64&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; - ttyAMA0 &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;

Run &lt;span class=&quot;s1&quot;&gt;&apos;nixos-help&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;the NixOS manual.

nixos login: builder &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;automatic login&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;builder@nixos:~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt;
Linux nixos 6.12.64 &lt;span class=&quot;c&quot;&gt;#1-NixOS SMP Thu Jan  8 09:15:06 UTC 2026 aarch64 GNU/Linux&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ctrl-Dを連打してもVMは止まらんので&lt;code&gt;shutdown now&lt;/code&gt;で終了する｡&lt;/p&gt;&lt;p&gt;VMが立ち上がったところで､ホスト側でおもむろに&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nix build .#packages.aarch64-linux.image &lt;span class=&quot;nt&quot;&gt;--no-link&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; image.tar.zst
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;を叩くとビルドに成功する｡&lt;code&gt;-L&lt;/code&gt;オプションなどつけてログを観察すると､linux-builderにcopyして生成物をpullしているのが見える｡&lt;/p&gt;&lt;p&gt;この手法の良い点は､Nixキャッシュがホスト側に保存されるところにある｡
ソースからderivationのハッシュが得られ､ &lt;em&gt;どうやって生成されるかにかかわらず&lt;/em&gt; ホスト側にderivationが得られれば&lt;code&gt;/nix/store&lt;/code&gt;に置かれるので､linux-builder上でビルドしてもOKなんやね｡
なのでlinux-builder VMを再起動したり変更をほどこしても､ちゃんと差分だけをビルドしてくれる｡&lt;/p&gt;&lt;hr&gt;&lt;p&gt;SSHでビルダーと通信できるちゅうことはリモートにビルドサーバを用意してもええわけですし､他にも&lt;a href=&quot;https://determinate.systems/blog/changelog-determinate-nix-384/&quot;&gt;Determinate Nixのnative Linux builder&lt;/a&gt;を利用してもよい｡
とまあやり方は様々だが簡単な順に&lt;sup id=&quot;fnref1&quot; title=&quot;これって私の感想ですよ &quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;2つ紹介した｡&lt;/p&gt;&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;

&lt;li id=&quot;fn1&quot;&gt;
&lt;p&gt;これって私の感想ですよ &lt;a href=&quot;#fnref1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 11 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://nymphium.github.io/2026/01/11/nix-image-build.html</link>
        <guid isPermaLink="true">https://nymphium.github.io/2026/01/11/nix-image-build.html</guid>
        
        <category>Nix</category>
        
        
      </item>
    
      <item>
        <title>依存関係をエフェクトで文脈に持ち上げる</title>
        <enclosure type="image/png" length="0" url="https://nymphium.github.io/pictures/github_icon.png"></enclosure>
        <description>&lt;p&gt;こんにちは､びしょ～じょです｡
脱毛にて､痛みで身体が震えることを知りました｡&lt;/p&gt;&lt;h1 id=&quot;1.+%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#1.+%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;1. はじめに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;さて､前回はレイヤードアーキテクチャ､特にDDDについて話した｡
またソフトウェアアーキテクチャ一般について､なぜそういったアーキテクチャを採用するのかとかちゃんとせいよという一般的な部分も触れた｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://nymphium.github.io/2025/12/14/ddd.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://nymphium.github.io/pictures/github_icon.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://nymphium.github.io/2025/12/14/ddd.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;アプリケーションの階層を再考し､ - lilyum ensemble&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;こんにちは､びしょ〜じょです｡11月26日といえば1､後醍醐天皇､Laz､おれの誕生日でした｡みんなは何人わかるかな?# ここに欲しいものリストを貼る        Amazonほしい物リストを...&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;今回は､具体的にOCamlでDDDを実装する際のポイントを紹介したい｡
再掲になるが以下に実装がある｡&lt;/p&gt;&lt;div class=&quot;github-widget&quot; data-repo=&quot;Nymphium/oresai&quot;&gt;&lt;/div&gt;&lt;p&gt;今回は結構簡素です｡&lt;/p&gt;&lt;h1 id=&quot;2.+%E5%9E%8B%E3%81%AE%E9%9A%A0%E8%94%BD%E3%81%A7%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%81%AE%E5%80%A4%E3%82%92%E7%B5%9E%E3%82%8B&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2.+%E5%9E%8B%E3%81%AE%E9%9A%A0%E8%94%BD%E3%81%A7%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%81%AE%E5%80%A4%E3%82%92%E7%B5%9E%E3%82%8B&quot;&gt;2. 型の隠蔽でドメインの値を絞る&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;まずはドメインオブジェクトをモデリングしていく｡
DDDはアプリケーションの不変条件としてドメインを置き､それらが不正な状態にならないことが重要になる｡
この実現のために､スマートコンストラクタなど特定のパスでバリデーションが通った値だけを生成したい｡&lt;/p&gt;&lt;p&gt;OCamlではopaque typesを使えばOKだが､エンティティ自体の型を隠蔽してしまうとフィールドアクセスが煩雑になる｡
そこで､ドメインオブジェクトの型のシェイプは公開し､ &lt;strong&gt;それぞれのフィールド(value objects)のみ&lt;/strong&gt; 隠蔽する｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;domains/objects/user.ml&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`InvalidFormat&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contains&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ok&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`InvalidFormat&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;email&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;Id&lt;/code&gt; の &lt;code&gt;from&lt;/code&gt;､&lt;code&gt;to_&lt;/code&gt;は単なる型変換だが､&lt;code&gt;Email&lt;/code&gt; の &lt;code&gt;from&lt;/code&gt; はバリデーションを行う｡
実装は&lt;code&gt;id&lt;/code&gt;関数になっており､単に型を隠蔽しているだけなのがテク｡
Signatureを定義できるって､うれしいなあ｡
これで &lt;code&gt;user.email&lt;/code&gt; など各フィールドへのアクセスはできつつも&lt;code&gt;Email.t&lt;/code&gt; がないとオブジェクト自体は作れない｡
したがって､あるオブジェクトがあれば､その各フィールドはdomain的に正しい値であることが保証される｡
いわゆる『Parse, don&apos;t validate』&lt;sup id=&quot;fnref1&quot; title=&quot;Parse, don&apos;t validate &quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;ですね｡
各フィールドは単にレコードのアクセスで済ませられ､フィールドの値の取り出しになって初めてdeconstructionする｡
値の生成=parsingになり､野良domain objectsが事実上存在しなくなり､バリデーションのロジックがdomain層に集約されるためapplication層での値のチェックが不要になる｡
しかも同型ならランタイムコストは実質0になる｡&lt;/p&gt;&lt;p&gt;同型…(ここで雷鳴) &lt;em&gt;ムムッ&lt;/em&gt; ､これは &lt;strong&gt;(準)同型変換&lt;/strong&gt; だな｡
各フィールドは同じように書けるんで､ファンクターを定義するとよさそう｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;domains/morph.ml&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Sealed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bwd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bwd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bwd&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SealedHom&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;(* 略 *)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bwd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bwd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Errors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* domain上のエラー *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Seal&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Sealed&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bwd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bwd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;with_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SealHom&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;(* 略 *)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SealedHom&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bwd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;(* 略*)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;validate&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ok&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`ConvertError&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;各フィールドの(準)同型変換を束ねるとドメインオブジェクトの変換になるんでproduct morphismと考えられますね｡
またそれぞれのフィールドはベースの型に戻るのでbifuntor､じゃな｡
&lt;code&gt;from&lt;/code&gt; &lt;code&gt;to_&lt;/code&gt; は &lt;code&gt;inj&lt;/code&gt; &lt;code&gt;prj&lt;/code&gt; とかにするとさらに雰囲気出そうですね｡
ちゃんと数学やってるともう少し意味のあることが言えそうですが､私は積み重ねてこなかった側なんで､詳しい話は冬休み中お家の人に聞いてみてね｡&lt;/p&gt;&lt;p&gt;Domain側の実装では脳に刺激が与えられ､caller側ではオブジェクトをシンプルに扱えるようになり､脳に良い～～｡&lt;/p&gt;&lt;h1 id=&quot;3.+%E4%BE%9D%E5%AD%98%E9%96%A2%E4%BF%82%E3%82%92%E3%82%A8%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88%E3%81%A7%E6%96%87%E8%84%88%E3%81%AB%E6%8C%81%E3%81%A1%E4%B8%8A%E3%81%92%E3%82%8B&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#3.+%E4%BE%9D%E5%AD%98%E9%96%A2%E4%BF%82%E3%82%92%E3%82%A8%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88%E3%81%A7%E6%96%87%E8%84%88%E3%81%AB%E6%8C%81%E3%81%A1%E4%B8%8A%E3%81%92%E3%82%8B&quot;&gt;3. 依存関係をエフェクトで文脈に持ち上げる&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Domainが実装できたので次いでrepositoriesとusecasesを定義しよう｡
バックエンドはinfrastructureにあるので､振る舞いそのものにだけ集中して書ける｡
書けるというか書くことになる｡
Usecasesはrepositoriesに依存することになるので､まあファンクターを使ってみましょうか…?&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;app/usecases/register_user.ml 一旦ファンクター&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Domains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Repositories&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Syntax&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Domains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Objects&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
      &lt;span class=&quot;nn&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mail&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;でもこれ…全部のusecaseでやるんすか?
この例では&lt;code&gt;M = User repository&lt;/code&gt;だけど､複数のreposをまたぐ場合 &lt;code&gt;New(M: R1)(N: R2)...&lt;/code&gt;で呼び出し側もえぐいど…｡&lt;/p&gt;&lt;p&gt;例えば皆さんご存知ライブラリOSのMirageOSはOCamlで実装されており各抽象レイヤーはファンクターで繋げられる｡
しかし複雑さが極まっているので､Functoriaという他段階計算を用いてビルド時にファンクター適用を解決するDSLを提供している｡
いやー俺達もすでに面倒そうなんですけど､DSL提供するという新たな痛みを生みたくないんですけど…｡&lt;/p&gt;&lt;center&gt;
&lt;b&gt;せや! エフェクトに頼ろう!&lt;/b&gt;
&lt;/center&gt;&lt;p&gt;というわけでeffectsを使って依存関係を &lt;em&gt;文脈&lt;/em&gt; に追いやって数珠つなぎの依存注入からプログラム､そして人類を解放する｡
Repositoriesの振る舞いをeffectsとして定義し､usecasesではそれを&lt;code&gt;perform&lt;/code&gt;するだけにする｡&lt;/p&gt;&lt;p&gt;各reposのeffectsをひとまとめにするために､まず&lt;code&gt;action&lt;/code&gt;というextensible variantを用意して､それをemitするeffectを定義する｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;domains/repositories/locator.ml&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* 一応ちなむと`..`はextensible variantの記法ですよ *)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Effect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Inject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Errors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;
           &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Effect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Effect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Inject&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;どんな値が欲しいかを書いてeffectを投げると､その値が返ってくるイメージ｡&lt;/p&gt;&lt;p&gt;実際の&lt;code&gt;action&lt;/code&gt;は各repositoryごとに定義する｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;domains/repositories/user.ml&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Locator&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Create&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Errors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;これの嬉しいところは､シグネチャと実装が分けられるうえに､シグネチャ(&lt;code&gt;action&lt;/code&gt;)を利用しないとeffectが投げられないため､強制的に一致する点だ｡
これでusecaseは次のように書ける｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;app/usecases/register_user.ml with effect&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Syntax&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Domains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Objects&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Domains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Repositories&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Locator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Create&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;依存が値の世界から文脈にアセンションされたため､インターフェイスが簡潔になった｡
簡潔になったんで､依存を最後の最後に結合するmainまで注入を考えなくてよくなった｡
脳に良すぎる…｡
同様に､usecasesで呼びたい外部サービスもeffectsとして定義して､それらをperformすればよい｡&lt;/p&gt;&lt;h2 id=&quot;3-1.+%E3%81%95%E3%82%89%E3%81%AB%E8%84%B3%E3%81%AE%E8%B2%A0%E6%8B%85%E3%82%92%E6%B8%9B%E3%82%89%E3%81%99%E3%81%8B%3F&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#3-1.+%E3%81%95%E3%82%89%E3%81%AB%E8%84%B3%E3%81%AE%E8%B2%A0%E6%8B%85%E3%82%92%E6%B8%9B%E3%82%89%E3%81%99%E3%81%8B%3F&quot;&gt;3-1. さらに脳の負担を減らすか?&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Repositoryのアクションのシグネチャが&lt;code&gt;Result.t&lt;/code&gt;を返すが､なくても良いかもしれない｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;omit Result&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;c&quot;&gt;(* domains/repositories/locator.ml *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Effect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Inject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;
           &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Effect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* domains/repositories/user.ml *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Create&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;えっじゃあミスったらどうするんですか?
どうするかをハンドラ側に委ねればよい｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;main/handler.ml&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repo_handler&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;th&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;th&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Inject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Create&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Infrastructure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;DB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Sql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ok&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conitnue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ok&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;おお確かに､ミスったら継続を捨てればよくて､最後にvalue handlerで&lt;code&gt;Ok&lt;/code&gt;に包めばよい｡
うーんでもどうかな､repository actionって失敗する可能性あるから&lt;code&gt;Result&lt;/code&gt;あってもいい気がする｡
極限までやりたいこと以外の処理を遅延させるか､失敗する可能性を明示するか､一旦トレードオフということで議論の余地を残しておきます｡&lt;/p&gt;&lt;h1 id=&quot;4.+%E7%B5%90%E3%81%B3%E7%9B%AE%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AEmain%3A+DDD+as+an+extensible+interpreter&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#4.+%E7%B5%90%E3%81%B3%E7%9B%AE%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AEmain%3A+DDD+as+an+extensible+interpreter&quot;&gt;4. 結び目としてのmain: DDD as an extensible interpreter&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;さて､usecaseが定義できた｡
実はinfrastructureもinterfaceも実装できている｡そういうことにしよう｡
実装は&lt;a href=&quot;https://github.com/Nymphium/oresai/blob/article20251126/server/infra/db/sql/users.ml&quot;&gt;/server/infra/db/sql/users.ml&lt;/a&gt;とか&lt;a href=&quot;https://github.com/Nymphium/oresai/blob/article20251126/server/interface/grpc/services/oresai/services/user.ml&quot;&gt;/server/interface/grpc/services/oresai/services/user.ml&lt;/a&gt;をみてね｡&lt;/p&gt;&lt;p&gt;そして依存解決をmainでおこなっていく｡&lt;/p&gt;&lt;p&gt;先程すこし書いたが､やってくるeffectsに対してハンドラを書けばよい｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;main/handler.ml&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repo_handler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;th&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;system&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;th&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;th&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Inject&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Ping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Infrastructure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ping&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;th&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;th&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Inject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Create&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Infrastructure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;DB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Sql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Sql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;system&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;th&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;このハンドラでプログラムを囲むだけで実行環境が渡せてしまう｡
大変簡単ですね｡&lt;/p&gt;&lt;p&gt;ここで､アーキテクチャの実装全体を俯瞰すると以下のような図になる｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/plaintext/plaintext-original.svg&quot; alt=&quot;plaintext&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;わかりやすい依存関係図&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot; data-lang=&quot;plaintext&quot;&gt;domains (repositories)
    ↑        ↑
    |        |
usecases     |
    ↑        |
    |        |
interface    |
    ↑        |
    |  ←ー infrastructure
    |        |
main (handlers)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Domainsでrepositoryを操作する語彙を定義し､usecaseでそれらを利用したあらたな語彙を定義し､interfaceでuseacsesの語彙を利用してアプリケーションの動作全体を記述する｡
そしてmainにて､usecaseの語彙－effectとして送出されるrepositoryの語彙－を解釈する｡&lt;/p&gt;&lt;p&gt;これって… &lt;em&gt;extensible interpreter&lt;/em&gt; パターンじゃないですか?
各層でDSLを定義し､語彙を追加していき､最後に解釈器を合成していく｡
Expression problemもeffect handlerで粉砕や｡
Webアプリケーションを作っていたつもりだが､いつのまにかDSLを定義し､インタプリタを記述していた｡
アプリケーションのロジックは純粋な計算の記述となっており､infrastructureにてランタイムのオペレーションを書き､mainで合成する｡
Extensible interpreter言いたいだけちゃうかって感じですが､まあなんかスッキリした気分なんでOKです｡&lt;/p&gt;&lt;h1 id=&quot;5.+%22%E5%89%AF%E6%AC%A1%E5%8A%B9%E6%9E%9C%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AE%22%E3%83%86%E3%82%B9%E3%83%88%E5%AE%B9%E6%98%93%E6%80%A7&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#5.+%22%E5%89%AF%E6%AC%A1%E5%8A%B9%E6%9E%9C%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AE%22%E3%83%86%E3%82%B9%E3%83%88%E5%AE%B9%E6%98%93%E6%80%A7&quot;&gt;5. &quot;副次効果としての&quot;テスト容易性&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;さて､みなさんテストは書いてくださいね｡
これまでテストの話は一切でてこなかったが､なんとこのアーキテクチャはテストが書きやすい｡
Domainsは言わずもがな､usecasesも副作用がeffectとして飛び出てくるので､ハンドラを書けば簡単にテストできる｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;app/usecases/test/register_user.ml&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;register_user&quot;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_case&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ok&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Quick&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fixture&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
          &lt;span class=&quot;nn&quot;&gt;Testing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fixture&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test&quot;&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test@example.com&quot;&lt;/span&gt;
            &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Locator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Create&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nn&quot;&gt;Alcotest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;check&apos;&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Domains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;same name&quot;&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Domains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unsafe_from&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nn&quot;&gt;Alcotest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;check&apos;&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Domains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;same email&quot;&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Domains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unsafe_from&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;test@example.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nc&quot;&gt;Ok&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fixture&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;failwith&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;unmatched&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;nn&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test&quot;&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;test@example.com&quot;&lt;/span&gt;
              &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Domains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Locator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Inject&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Effect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Deep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inj&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;Alcotest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;check&apos;&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int64&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Errors&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;equal&quot;&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Ok&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Domains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fixture&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;特別なモックライブラリなどは不要で､effect handlerを書くだけでOK｡&lt;/p&gt;&lt;h1 id=&quot;6.+%E4%BD%99%E8%AB%87%3A+OCaml%E3%81%A7gRPC%E3%81%AF%28%E4%B8%80%E5%BF%9C%29%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%97%EF%BD%A4dune%E3%81%A8eio%E3%81%AF%E5%81%89%E5%A4%A7&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#6.+%E4%BD%99%E8%AB%87%3A+OCaml%E3%81%A7gRPC%E3%81%AF%28%E4%B8%80%E5%BF%9C%29%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%97%EF%BD%A4dune%E3%81%A8eio%E3%81%AF%E5%81%89%E5%A4%A7&quot;&gt;6. 余談: OCamlでgRPCは(一応)できるし､duneとeioは偉大&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;今回はNix上に環境を作り､PostgreSQL+&lt;a href=&quot;https://atlasgo.io/&quot;&gt;Atlas&lt;/a&gt;でDBを用意し､&lt;a href=&quot;https://buf.build/&quot;&gt;buf&lt;/a&gt;でprotobufをコンパイルする流れになった｡
だいたい毎度OCamlでアプリケーションを書くとどこかにPRを出す必要が生まれるが､nixではopam-nixにまずPRを投げた｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://github.com/tweag/opam-nix/pull/134&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://opengraph.githubassets.com/c5e3df14adb98b948d1cff68a9d503c0f93fa1f4a28ecc7f71883cc9d767d442/tweag/opam-nix/pull/134&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://github.com/tweag/opam-nix/pull/134&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Add openssl to add libssl for conf-postgresql in overlay by Nymphium · Pull Request #134 · tweag/opam-nix&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;This PR adds nixpkgs.openssl to conf-postgresql buildInputs.libpq provided by nixpkgs is not linked to libssl:$ pkg-config --print-errors libpqPackage libssl was not found in the pkg-config sear...&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;Nixpkgsのハッシュによってはopensslなどが必要になるバージョンが降ってくるんで､それの対応ですね｡&lt;/p&gt;&lt;p&gt;またgRPCのreflectionのためにOCamlのprotoc pluginにPRを出した｡
自分の都合でpendingさせてしまっているが､マージされたら皆さんもgrpcurlなどを叩く際にパラメータをいくつか省略できるようになるだろう｡
gRPC reflectionは所与のものとして考えていたので､実装方法が知れて勉強になった｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://github.com/andersfugmann/ocaml-protoc-plugin/pull/50&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://opengraph.githubassets.com/de6194dde7dc118809a8e2712852ccf203e890f22134d5b04c27aca74c4578b9/andersfugmann/ocaml-protoc-plugin/pull/50&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://github.com/andersfugmann/ocaml-protoc-plugin/pull/50&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Add metadata for gRPC reflection API by Nymphium · Pull Request #50 · andersfugmann/ocaml-protoc-plugin&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;This PR adds Metainfo module to each generated files.That module has information to implement gRPC reflection API:file name: its source proto file name pathfile descriptor: protobuf binary form...&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;さて書き味でいうと､EioのおかげでだいぶIO周りが書きやすくなったし､対応しているライブラリもだいぶ多く､困らない｡
今回はgRPCサーバの実装に&lt;a href=&quot;https://github.com/dialohq/ocaml-grpc&quot;&gt;ocaml-grpc&lt;/a&gt;のeioランタイムを利用した｡
ocaml-grpcはリクエストごとにスレッドを作るが､スレッドをまたぐeffectの送出はできないため､ハンドラごとに渡すことになった｡
スレッドをまたげない理由は『Retrofitting effect handlers over OCaml』に載ってた気がするが､単にスレッドをまたいでどうやって継続を呼ぶかあたりっすね｡なかったらすまん｡
論文の解説は以下に書いた｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://nymphium.github.io/2023/01/22/retrofitting_effect_handlers_onto_ocaml.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://nymphium.github.io/pictures/github_icon.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://nymphium.github.io/2023/01/22/retrofitting_effect_handlers_onto_ocaml.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Retrofitting Effect Handlers onto OCaml - lilyum ensemble&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;あけましておめでとうございます､びしょ～じょです｡これは言語実装Advent Calendar2022 17日目の記事です｡諸事情ありましたが端的に申し上げると私の怠慢で大幅に投稿日が遅れました...&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;Duneも3.20を利用しており､&lt;code&gt;include_subdirs&lt;/code&gt;やruleのdepsにディレクトリを指定できたりとモダンなビルドシステムとしての成熟を見せている｡
&lt;code&gt;include_subdirs&lt;/code&gt;はディレクトリを掘るとそのディレクトリ名と内容に対応したモジュールを生成してくれるというもので､そんなんできてあたりめーだろってのが､無かったんすねえ｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://dune.readthedocs.io/en/stable/reference/dune/include_subdirs.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://dune.readthedocs.io/en/stable/reference/dune/include_subdirs.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;include_subdirs - Dune documentation&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;モジュールあんだからなくていいだろっていうミニマリズムがあったと思うんですが､ビルドシステムが持ってくれてたほうが便利なんで､ありがとう｡&lt;/p&gt;&lt;h1 id=&quot;7.+%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#7.+%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;7. おわりに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;味噌スープ&lt;/p&gt;&lt;p&gt;よいおとしを&lt;/p&gt;&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;

&lt;li id=&quot;fn1&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/&quot;&gt;Parse, don&apos;t validate&lt;/a&gt; &lt;a href=&quot;#fnref1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 28 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://nymphium.github.io/2025/12/28/ddd2.html</link>
        <guid isPermaLink="true">https://nymphium.github.io/2025/12/28/ddd2.html</guid>
        
        <category>DDD</category>
        
        <category>OCaml</category>
        
        <category>Algebraic Effects</category>
        
        
      </item>
    
      <item>
        <title>アプリケーションの階層を再考し､</title>
        <enclosure type="image/png" length="0" url="https://nymphium.github.io/pictures/github_icon.png"></enclosure>
        <description>&lt;p&gt;こんにちは､びしょ〜じょです｡&lt;/p&gt;&lt;p&gt;11月26日といえば&lt;sup id=&quot;fnref1&quot; title=&quot;この記事は11月26日に執筆を開始した &quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;､後醍醐天皇､Laz､おれの誕生日でした｡みんなは何人わかるかな?&lt;/p&gt;&lt;p&gt;# ここに欲しいものリストを貼る&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://www.amazon.jp/hz/wishlist/ls/ZOVWRPLLOMCI&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://m.media-amazon.com/images/G/01/wishlist/collablists_graphic_2x_1060x768._CB454600986_.jpg&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://www.amazon.jp/hz/wishlist/ls/ZOVWRPLLOMCI&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Amazonほしい物リストを一緒に編集しましょう&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;h1 id=&quot;1.+%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#1.+%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;1. はじめに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;世の中にはレイヤードアーキテクチャないしはDDDの実践を謳うソフトウェアプロジェクトが多く存在する｡
しかし､その実態のいくつかは､部分的または全くもって､うまくいってない｡&lt;/p&gt;&lt;p&gt;なるほど一見してわかりやすいディレクトリ構成…? よくみたら抽象度がまばらでまるで迷宮｡
レイヤードのためのレイヤー構造｡
依存関係がぐちゃぐちゃでドメインロジックやビジネスロジックが渾然一体となっている｡
ドメインドリブンとはドメインドリブンのことなのだが｡
新規実装はどこに何を置けばいいですか?
変な位置にあるこの関数の処遇は誰に聞けばいいですか?&lt;/p&gt;&lt;p&gt;なぜこんなことに…いや､そもそもレイヤードな構造はなぜ在り､これらは何に失敗しているのか?
というのを自分でgRPCサーバを実装していたら思った｡
筆者は個人的にはライブラリか言語処理系しか書いてこなかったんで､アーキテクチャを真面目に考えたりすることも無かったんでよかった｡
よかったんで書きます｡&lt;/p&gt;&lt;div class=&quot;github-widget&quot; data-repo=&quot;Nymphium/oresai&quot;&gt;&lt;/div&gt;&lt;p&gt;本 &lt;em&gt;連載&lt;/em&gt; では､ソフトウェア開発におけるレイヤードアーキテクチャの意義を､人間の認知負荷の観点から再考し､OCamlを用いて実践､さらに発展的な手法､考察をおこなう｡
まず､レイヤードアーキテクチャが脳の認知負荷を下げることを確認し､次いでDDDにおけるレイヤー分割の判断基準をフローチャートで整理して混乱がおこらないようにする｡
実装ではopaque typesとモジュールを利用してドメインの生成を絞り､エフェクトハンドラを利用してレイヤー境界である依存関係を値から文脈の世界に追い出す｡
実装を経てアーキテクチャ全体を見たときに､extensible interpreterと構造が共通していることに気づく｡
最後に､副次効果としてテスト容易性が得られることを確認する｡&lt;/p&gt;&lt;p&gt;ゴチャゴチャ日本語を書くパートが長くなったんで2分割した｡
連載と言っているがこれと実装の2回を想定している｡
本項では前半部分､レイヤードアーキテクチャの意義とDDDにおけるレイヤー分割のフローチャートまでを示す｡&lt;/p&gt;&lt;p&gt;一応想定しているアプリケーションとしては､ビジネスアプリケーションというかWebアプリケーションになる｡
言語処理系はパイプラインアーキテクチャになりそうだし､OSなども全く違う作りだろう｡
とはいえアーキテクチャをちゃんとアプリケーションに沿って真面目に考えましょうとか認知負荷のあたりは後述するが普遍的な話やと思います｡&lt;/p&gt;&lt;h1 id=&quot;2.+%E3%81%9D%E3%82%82%E3%81%9D%E3%82%82%E4%BD%95%E3%81%8CDDD%E3%82%84%E3%81%AD%E3%82%93%E3%81%A8&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2.+%E3%81%9D%E3%82%82%E3%81%9D%E3%82%82%E4%BD%95%E3%81%8CDDD%E3%82%84%E3%81%AD%E3%82%93%E3%81%A8&quot;&gt;2. そもそも何がDDDやねんと&lt;/a&gt;&lt;/h1&gt;&lt;h2 id=&quot;2-1.+%E3%83%AC%E3%82%A4%E3%83%A4%E3%83%BC%E3%83%89%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E3%81%AE%E5%AD%98%E5%9C%A8%E7%90%86%E7%94%B1&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2-1.+%E3%83%AC%E3%82%A4%E3%83%A4%E3%83%BC%E3%83%89%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E3%81%AE%E5%AD%98%E5%9C%A8%E7%90%86%E7%94%B1&quot;&gt;2-1. レイヤードアーキテクチャの存在理由&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;抽象化する理由はなにか? それは &lt;strong&gt;&lt;em&gt;いま&lt;/em&gt;&lt;/strong&gt; &lt;strong&gt;集中したいこと&lt;/strong&gt; とどうでもいいことを分けるため｡
例えば&lt;code&gt;Functor&lt;/code&gt;｡コンテナの構造には興味がなく､中身&lt;code&gt;a&lt;/code&gt;が&lt;code&gt;b&lt;/code&gt;に変化することにだけ興味がある｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/haskell/haskell-original.svg&quot; alt=&quot;haskell&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;抽象化の例のためだけにここでだけHaskellを使います&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-haskell&quot; data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;kr&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;where&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;-- コンテナfがListなのかMaybeなのかに関心なし&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;add1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;add1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;--- ここまで中身に興味なし ---&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;add1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;-- [2,3,4]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;add1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;-- Just 4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;レイヤードアーキテクチャも同様に､レイヤー外部のことに関心を持たず､&quot;いま&quot;集中したいことにだけをレイヤーごとに記述する｡
アプリケーション中のエンティティについて考えるとき､DBの都合には関心がない｡&lt;/p&gt;&lt;h3 id=&quot;2-1-1.+%E8%AA%8D%E7%9F%A5%E8%B2%A0%E8%8D%B7%EF%BD%A4%E5%87%9D%E9%9B%86%E5%BA%A6%E3%81%A8%E7%B5%90%E5%90%88%E5%BA%A6&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2-1-1.+%E8%AA%8D%E7%9F%A5%E8%B2%A0%E8%8D%B7%EF%BD%A4%E5%87%9D%E9%9B%86%E5%BA%A6%E3%81%A8%E7%B5%90%E5%90%88%E5%BA%A6&quot;&gt;2-1-1. 認知負荷､凝集度と結合度&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;なぜ集中するために抽象化して関心のないものを削ぎ落とすのか?
理由の一つに､人間のワーキングメモリが一度に保持できる情報のチャンクは &lt;em&gt;7つ&lt;/em&gt; 前後&lt;sup id=&quot;fnref2&quot; title=&quot;Mark Seemann. 『脳に収まるコードの書き方』. オライリー･ジャパン. 2024. 長年の経験に裏打ちされた著者なりのプログラミング哲学や著名人からの学びが､example projectを作る過程でつらつらと述べられている｡ページを捲るたびにハッとすることが多い｡良書 &quot;&gt;&lt;a href=&quot;#fn2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;と非常に小さいことが挙げられる｡
例えば新たな仕事先で巨大なコードがまったく抽象化されずに書かれていたら､実際に開発に着手できるようになるまで大変な時間がかかるだろう｡
一つの関数に､まずDB操作が始まり､業務仕様があり､エラー制御があり､ワーオDBの中間テーブルのオブジェクトをまた操作してる…そしてAPIレスポンスにパッキングして､とフラットに書かれていたら､文字通り &lt;em&gt;脳がパンクする&lt;/em&gt; のだ｡
あまりにも大きな認知負荷で全くコードが読めない｡読む気にならない｡&lt;/p&gt;&lt;p&gt;これを解決するための構造的特性が､ソフトウェアアーキテクチャにおける &lt;strong&gt;高凝集･疎結合&lt;/strong&gt; だ&lt;sup id=&quot;fnref3&quot; title=&quot;Mark Richards, Neal Ford. 『ソフトウェアアーキテクチャの基礎』. オライリージャパン. 2022. やりたいこと､できることに応じたソフトウェアアーキテクチャが並んでいる｡アーキテクチャを考えるにあたっての指標も並んでおり､どこを目指せばよいかも考えられるし現状の診断もできるようになる &quot;&gt;&lt;a href=&quot;#fn3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;｡
凝集度はコンポーネントが一つの目的に集中している度合いを指し､結合度はコンポーネント間の依存関係の強さを指す｡
上記のようなベチャッとした平たいコードはいろんな関心が集まっているので凝集度が低い｡
全てが一つのコンポーネントに詰め込まれているので､他のコンポーネントからの依存が強く結合度も高まる｡
何も考えず単にフラットなコードというのは､単にソフトウェアアーキテクチャ的観点からも品質が低いことが指摘できる｡&lt;/p&gt;&lt;p&gt;まず凝集度について｡
凝集度にも種類があり､単にファイルが分割されただけでその中身のエントリーの関係性が薄い場合(偶発的凝集)は意味をなさない｡
目指すべきは機能的凝集であり､一つのコンポーネントが一つの目的に強く関連するエントリーを持つことである｡&lt;/p&gt;&lt;p&gt;次いで結合度に思いを馳せる｡
抽象度が高く､外部への依存が少ないコンポーネントは､他のコンポーネントからの依存関係が弱くなる｡
こちらも抽象化･隠蔽に失敗して内部データや実装がリークする内部結合から､プリミティブ型などそれ以上の詳細がない型だけが行き来するデータ結合を目指したい｡&lt;/p&gt;&lt;p&gt;結合度が低いとレイヤーの移動で抽象度や対象が適切に切り替わって垂直方向に対する脳の負荷が下がり､高凝集だと至ったレイヤーでどのコンポーネントを参照すればよいか迷子にならず水平方向で脳への負荷が下がる｡
ビジネスロジックでドメインオブジェクトを触るときに疎結合のおかげでDBでの表現について(&quot;今は&quot;)考える必要がなくなり､コンポーネントが高凝集だと特定の外部サービスの抽象化されたAPI呼び出しがどこにあるか迷わなくなる｡
つまりレイヤードアーキテクチャは､抽象度という視点でコードを縦横に割り､高凝集なチャンクにまとめ､疎結合な境界線を引くことで､ハードウェア性能の高くない人間一般の脳でもその認知を超える巨大なシステムが扱えるようになる道具なのだ｡&lt;/p&gt;&lt;h3 id=&quot;2-1-2.+%E5%88%86%E5%89%B2%E3%81%AE%E8%BB%B8%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AEDDD&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2-1-2.+%E5%88%86%E5%89%B2%E3%81%AE%E8%BB%B8%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AEDDD&quot;&gt;2-1-2. 分割の軸としてのDDD&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;｢では高凝集疎結合にしよう!｣となったんですが､具体的にはどうやって?
結局ここでうまくレイヤーやコンポーネント分けに失敗すると脳に悪いアーキテクチャが生まれてしまう｡
そこでDDDを使う｡
まずアプリケーションにおける &lt;strong&gt;ドメイン&lt;/strong&gt; ､つまりプロダクトの扱うエンティティ､その間の制約､計算方法､など抽出された根幹部分を &lt;em&gt;絶対的な軸&lt;/em&gt; として用意し､そこからの相対としてビジネスロジックや外部との接続を定義していく｡
ここを軸にすると､DDDの依存の方向と同様に2つの概念が得られる:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Usecases … ドメインに関係や動きを生む&lt;/p&gt;

&lt;p&gt;ドメインは在り方､あるいは生まれ方や変わり方と消え方､つまりルールだけがあるので､これらをインタラクトさせる必要がある｡
ユースケースにはドメインの動きを記述する｡
例えば&quot;ドメインのルールで値をチェックし､それらを保存する&quot;とか｡&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Infrastructure … アプリケーション外部との接続&lt;/p&gt;

&lt;p&gt;でもユースケースはピュアに書きたい｡
だってドメインの動きを書くだけなのにDBのコネクションエラーや外部APIのエラーなんて&quot;今は&quot;関係ないはずでしょ?
そこでユースケースはドメインの動きの記述に &lt;em&gt;集中&lt;/em&gt; し､実際の外部との接続はインフラ層と呼ぶ場所に任せる｡
外部とはDB､Web API､ファイルシステム､などなど｡&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;ドメインを軸にすると決めることで､それを動かすためのユースケースが生まれ､ユースケースがドメインの動きのモデリングに集中するために実際に外部サービスを呼び出す場としてインフラ層が生まれる｡
ドメインを中心においた場合の解の一つとしてDDDが得られる｡&lt;/p&gt;&lt;h3 id=&quot;2-1-3.+%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E3%81%AE%E5%AD%98%E5%9C%A8%E7%90%86%E7%94%B1%3A+%E8%AA%8D%E7%9F%A5%E6%91%A9%E6%93%A6%E3%81%AE%E8%A7%A3%E6%B6%88%EF%BD%A4%E3%82%B3%E3%83%B3%E3%82%A6%E3%82%A7%E3%82%A4%E3%81%AE%E6%B3%95%E5%89%87&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2-1-3.+%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E3%81%AE%E5%AD%98%E5%9C%A8%E7%90%86%E7%94%B1%3A+%E8%AA%8D%E7%9F%A5%E6%91%A9%E6%93%A6%E3%81%AE%E8%A7%A3%E6%B6%88%EF%BD%A4%E3%82%B3%E3%83%B3%E3%82%A6%E3%82%A7%E3%82%A4%E3%81%AE%E6%B3%95%E5%89%87&quot;&gt;2-1-3. ソフトウェアアーキテクチャの存在理由: 認知摩擦の解消､コンウェイの法則&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;ここまで個々人の脳の認知負荷を考えてきた｡
個人的な感覚の開発風景からチーム開発に話を移してみると､いろんな人間の脳が出てきて､いろんなキャパシティの脳が人間というインターフェイスでコミュニケーションを取り合い､ときに認知力や認識方法の違いで摩擦を感じ､疲労する｡
ソフトウェアアーキテクチャを決定し､&quot;どこに何を配置するか&quot;に制約をつくることで､チーム全体が共有するメンタルモデルを統一し､摩擦の発生を抑えられる｡
ソフトウェアアーキテクチャがレイヤードであることに重要さは必ずしもないが､ソフトウェアアーキテクチャが定まっており &lt;strong&gt;厳密に実施されている&lt;/strong&gt; ことは重要である｡&lt;/p&gt;&lt;p&gt;このロジックはどこに書くのか? —— ある人はドメイン､また別の人はインフラに置くべきだと考える｡
この認知のズレがコミュニケーションに摩擦を生み､全体的な開発スピードが低下していく｡
ソフトウェアアーキテクチャによってどこに何を配置するかを強制･実践していくことで､皆が同意できる自明な場所にて解決され､上記のような議論が発生しなくなる｡
厳密な実践を続け､形骸化した謎の三層アーキテクチャにしないことまでが重要になる｡&lt;/p&gt;&lt;p&gt;このコードの構造と組織の認知の関係性は､まさにコンウェイの法則の指摘するそれである｡
上記で述べたように､ソフトウェアの構造がカオスであれば組織間のコミュニケーションパスもまたカオスになるという､ある種の &lt;strong&gt;セカイ系的な&lt;/strong&gt; 繋がりがある｡
手元にあるソフトウェアの構造の解決で､コミュニケーションコストの解決がなされるわけだ｡
ハッキングから今晩のおかずまで同一コンポーネントに記載された凝集度の低い場所からは､様々な内容の議論がチーム内のあちこちで発生するだろう｡
結合度の高い箇所で実装に関する議論を始めたら､バックエンド､フロントエンド､SRE､更にはPMを引っ張り出して話をする必要があるかもしれない｡&lt;/p&gt;&lt;p&gt;このコミュニケーションコストの問題は､往々にして組織運営などで解決する傾向が見られる&lt;sup id=&quot;fnref4&quot; title=&quot;著者調べ &quot;&gt;&lt;a href=&quot;#fn4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;｡
コミュニケーションコストのために更にミーティングが増える｡
しかし根本的な問題というのは議論が必要なソフトウェア側にあるため､ミーティングのためのミーティングはそのことを看破できる場たりえるが､そうでなければただただコミュニケーションコストが肥大化するだけだ｡
確かに問題を認識していてもリアーキテクチャは腰が重い｡
実装も時間がかかる｡
しかしやらない場合､増えたミーティングの時間もなくならない｡
マイクロサービスのような高階のアーキテクチャならば尚更､配置の議論の複雑さが高まるだろう｡&lt;/p&gt;&lt;p&gt;&quot;どうあるべき&quot;が掲げられ､それに沿って作られているのが望ましいが､歴史的経緯により偶発的に積み上げられた実装の地層も多く存在する｡
それでも､&quot;&lt;em&gt;本来&lt;/em&gt; どうあるべき&quot;という眼差しを改めて向けることはできるし､その新たな眼差しを共有できれば､実装も変わりコミュニケーションコストも少しずつ減っていくんではないか｡
読者の皆さんとこの眼差しを共有するため､本項ではとりあえず次章のフローチャートを提案する｡&lt;/p&gt;&lt;h3 id=&quot;2-1-4.+%E3%81%A1%E3%81%AA%E3%81%BF%E3%81%AB%3A+%E3%83%AC%E3%82%A4%E3%83%A4%E3%83%BC%E3%82%84DDD%E3%81%AF%E5%BF%85%E7%84%B6%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%84%E3%81%97%EF%BD%A4%E9%81%A9%E3%81%95%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88%E3%82%82%E3%81%82%E3%82%8B&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2-1-4.+%E3%81%A1%E3%81%AA%E3%81%BF%E3%81%AB%3A+%E3%83%AC%E3%82%A4%E3%83%A4%E3%83%BC%E3%82%84DDD%E3%81%AF%E5%BF%85%E7%84%B6%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%84%E3%81%97%EF%BD%A4%E9%81%A9%E3%81%95%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88%E3%82%82%E3%81%82%E3%82%8B&quot;&gt;2-1-4. ちなみに: レイヤーやDDDは必然ではないし､適さない場合もある&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;当然だがレイヤードアーキテクチャは必然のものではない｡&lt;/p&gt;&lt;p&gt;&lt;code&gt;まずDB操作が始まり､業務仕様があり､エラー制御があり､ワーオDBの中間テーブルのオブジェクトをまた操作してる…そしてAPIレスポンスにパッキングして&lt;/code&gt; を一つの関数でおこなうことは､例えばシェルスクリプトでは､適当なハッシュテーブルをインメモリDBと考えれば､よく書くだろう｡
これでワークする理由は､コード全体が小さいから(そう､ですよね…?)｡
他にもいくつかの理由でレイヤードアーキテクチャたりえない場合がある｡たとえば:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;単純なCRUD&lt;/li&gt;
&lt;li&gt;データ変換&lt;/li&gt;
&lt;li&gt;ハイパフォーマンスが必要な場合&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;1.はシェルスクリプトと概ね同じ理由で､コード全体が小さく脳への負荷が小さい場合｡
2.は､単にデータ形式を変換するだけであり､ビジネスロジックが存在しない場合｡それぞれの変換レイヤーがデータの内容を知っていればよいため(ここで&lt;code&gt;fmap&lt;/code&gt; を思い出す)｡
3.は､レイヤー分割による抽象化オーバーヘッドが性能に悪影響を与える場合｡&lt;/p&gt;&lt;p&gt;&quot;今&quot;解きたい問題が脳への負荷だったので解法の一つとしてレイヤードアーキテクチャを選択したにすぎない｡
そしてDDDもまたそうであり､主題としてドメインを固定したゆえにDDDになっただけである｡
例えばすでにデータベースにデータがあり単純な構造ならばトランザクションスクリプトパターンが適しているかもしれないし&lt;sup id=&quot;fnref5&quot; title=&quot;本当に 単純な場合に限る &quot;&gt;&lt;a href=&quot;#fn5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;､既存とは毛色の機能を追加したい場合は別のアプリケーションに切り出してマイクロサービスなどといった高階のアーキテクチャに話が移っていく｡
プロダクトの提供したい価値や業界によってはもっと別のアーキテクチャ特性にフォーカスしたい場合もある｡
大事なのは､そのアーキテクチャで何を解決したいかを明確にすること｡
DDDの実施ができてない場合は､ただの理解不足なだけではなくDDD自体がアプリケーションや解決したい問題にフィットしていない可能性もありえる｡&lt;/p&gt;&lt;h2 id=&quot;2-2.+%E3%83%95%E3%83%AD%E3%83%BC%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88%E3%81%A7%E8%84%B3%E3%81%A8%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E6%95%B4%E7%90%86%E3%81%99%E3%82%8B%3A+%E3%82%AA%E3%83%8B%E3%82%AA%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2-2.+%E3%83%95%E3%83%AD%E3%83%BC%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88%E3%81%A7%E8%84%B3%E3%81%A8%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E6%95%B4%E7%90%86%E3%81%99%E3%82%8B%3A+%E3%82%AA%E3%83%8B%E3%82%AA%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3&quot;&gt;2-2. フローチャートで脳とプロジェクトを整理する: オニオンアーキテクチャ&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;先に述べたようにDDDには3つの概念､domains, usecases, infrastructureがある｡
ここですこし構造を整理する｡
突然ですが &lt;em&gt;application&lt;/em&gt; というレイヤーを用意します｡
その中にusecaseを置く｡
Applicationでは&quot;アプリケーションが何を達成するか&quot;を記述する｡
なぜそんなことを?
アプリケーションはときに外部サービスとの通信が必要になる｡
ここでもその外部サービスが何をしてくれるかにのみ関心があるため､外部サービスのインターフェイスを記述する｡
この外部サービスとdomainにあるrepositoryを操作して､usecaseにアプリケーションの振る舞いが書かれる｡
これにより､applicationを覗くだけで&quot;何が必要で､何ができるか&quot;が一目瞭然となり､脳にいいですねえ｡&lt;/p&gt;&lt;p&gt;Usecaseないしはapplicationの立ち位置がスッキリしたので､infrastructureもスッキリさせる｡
Applicationはアプリケーションのこと &lt;em&gt;だけ&lt;/em&gt; を考えたい､いわば &lt;strong&gt;内側&lt;/strong&gt; の世界だった｡
ともすれば､infrastructureはアプリケーションの &lt;strong&gt;外側&lt;/strong&gt; の世界にあたる｡
外界には､こちら(アプリケーション)から外界に働きかける場合と､外界から働きかけを受ける場合の2つのふれあい方がある｡
働きかける場合は､例えばDBにデータを保存したり､外部APIを呼び出したりする場合｡
これらはinfrastructureに置く｡
働きかけを受ける場合というのは､gRPCリクエストを受け取ったりHTTPリクエストを受け取ったりする場合｡
これらは &lt;em&gt;interface&lt;/em&gt; に置く｡
なるほどたしかに､外界から見ればprotobufやAPI schemaはインターフェイスですね｡
またインターフェイスかよって思うかもしれないが､OCamlerはこれ以外のinterfaceをsignatureと考えてくれればスッキリするんで､静かに｡&lt;/p&gt;&lt;p&gt;アプリケーションの内･外､さらに内側の階層…という構造から､これは(オニオンアーキテクチャ &amp;lt;: DDD)と呼ばれることもある｡
依存の方向性がすべて内側にのみ向かっており､最内のドメインは何にも依存しない真実のみが記載される｡
このルールによって､それぞれはそれらの内側の知識だけあれば書けるようになっており､脳への負荷が下がる｡&lt;/p&gt;&lt;p&gt;ということで言い訳が終わり､もう少し解像度をあげるためにフローチャートで見ていく｡&lt;/p&gt;&lt;p&gt;&lt;label id=&quot;flowchart&quot;&gt;&lt;/label&gt;
&lt;/p&gt;&lt;div&gt;


&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot; data-lang=&quot;plaintext&quot;&gt;START: コード化しようとしている概念
               ⇓
Q1. それはアプリケーション上の知識やルールか?
    (例: データの整合性､計算ロジック､状態遷移のルール)
    ├─ Yes → Domains: Object (entity) / Value / Repository
    │        アプリケーション上の存在の定義
    └─ No ↓
Q2. アプリケーションの挙動そのものか?
    (例: &quot;登録&quot;というタスクのステップ､&quot;送金&quot;の手順)
    ├─ Yes → Application: UseCase / Service Intf.
    │        知識と外部への要求を呼び出して処理の手順を記述する
    │        外部サービスのインターフェイス
    └─ No ↓
Q3. それは外部からの入力を受け付ける窓口か?
    (例: gRPCリクエスト受け取って処理する)
    ├─ Yes → Interface: gRPC handler / HTTP Controller
    │        外部から入力を受け取り､アプリケーションを実行する
    │        UseCaseを呼び出すアダプター
    └─ No ↓
Q4. その機能はIOを発火する?
    ├─ Yes → Infastructure: DB / Service Impl.
    │        Repositoryや外部サービスの実装
    │        DB､乱数生成器､外部サービスの実際のAPI呼び出しなど
    └─ No → Domain Service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
図&lt;a href=&quot;#flowchart&quot;&gt;2.1&lt;/a&gt;. フローチャートでDDDのレイヤー分割を考える
&lt;/center&gt;

&lt;p&gt;&lt;/p&gt;
&lt;/div&gt;&lt;p&gt;このフローチャートで最も重要なことは､とにかく &lt;strong&gt;(この)ルールを厳守し続けること&lt;/strong&gt; である｡
例外ができるとアーキテクチャの前提が崩れ､レイヤーを突き抜けていく例外の周辺で認知負荷が上昇し､レイヤードアーキテクチャないしはDDDのうまあじが破壊される｡
ルールが厳守されないと､コミュニケーションの摩擦がちょうどその箇所から新たに発生していくだろう｡
御プロジェクトに特殊な事項がある場合は､まず実装上も特殊な事項なのかを熟考していただき､その場合DDDに例外を突っ込むのが正しいのか､別のアーキテクチャにすべきかは検討してほしい｡
御プロジェクトは多分ユニークだと思いますが､他のプロジェクトも &lt;em&gt;同様にユニークな&lt;/em&gt; 価値提供をしているんで &lt;em&gt;逆に&lt;/em&gt; 実装として特殊なケースは多くない｡&lt;/p&gt;&lt;p&gt;これらを反映すると以下のようなディレクトリ構造になる(図&lt;a href=&quot;#dir_structure&quot;&gt;2.2&lt;/a&gt;)｡&lt;/p&gt;&lt;p&gt;&lt;label id=&quot;dir_structure&quot;&gt;&lt;/label&gt;
&lt;/p&gt;&lt;div&gt;


&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot; data-lang=&quot;plaintext&quot;&gt;/(root)
  ├─ domains
  │    ├─ objects
  │    └─ repositories
  ├─ application
  │    ├─ usecases
  │    └─ services
  ├─ infrastructure
  │    ├─ db/sql
  │    └─ services
  ├─ interface
  │     └─ grpc
  └─ main
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
図&lt;a href=&quot;#dir_structure&quot;&gt;2.2&lt;/a&gt;. フローチャートのなす構造の例
&lt;/center&gt;

&lt;p&gt;&lt;/p&gt;
&lt;/div&gt;&lt;p&gt;ログやメトリクスなどのアプリケーションの運用上必要になるメタ的なものは登場していない｡
これらはレイヤーをまたいで直で現れる場合がある｡メタいので｡
いわゆるアスペクト指向プログラミングの領域になり､それらの実践は言語やツールに依存することになる｡&lt;/p&gt;&lt;h1 id=&quot;3.+%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#3.+%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;3. おわりに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;書いてくうちにどんどん日本語がデカくなってしまったので二部構成にした｡
実装の話は次回｡&lt;/p&gt;&lt;p&gt;コンウェイの法則については筆者はこれまでピンと来ていなかったが､本項をまとめるうちににわかに理解できてきた｡
つまり書いてる途中は(書いたあとも)理解が浅かった｡
この記事が面白かった｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://qiita.com/hirokidaichi/items/d12fcce80ee593bcf34d&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Fadvent-calendar-ogp-background-7940cd1c8db80a7ec40711d90f43539e.jpg%3Fixlib%3Drb-4.1.1%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFtYXpvbmF3cy5jb20lMkYwJTJGMzU2NzElMkZwcm9maWxlLWltYWdlcyUyRjE1NDU3OTEwNDc_aXhsaWI9cmItNC4xLjEmYXI9MSUzQTEmZml0PWNyb3AmbWFzaz1lbGxpcHNlJmJnPUZGRkZGRiZmbT1wbmczMiZzPWI2ZGNjYTEzMGYyZDE4M2JlNzkxOTYwNGJlOGQzNDMw%26blend-x%3D120%26blend-y%3D462%26blend-w%3D90%26blend-h%3D90%26blend-mode%3Dnormal%26mark64%3DaHR0cHM6Ly9xaWl0YS1vcmdhbml6YXRpb24taW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnMzLWFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkZxaWl0YS1vcmdhbml6YXRpb24taW1hZ2UlMkZmMzY0ZWRkZWYyNTViYzY5NDVhMGQ3NDczNzY1NjgwYzczMjkzNWIyJTJGb3JpZ2luYWwuanBnJTNGMTQ4NjM0NjAxMz9peGxpYj1yYi00LjEuMSZ3PTQ0Jmg9NDQmZml0PWNyb3AmbWFzaz1jb3JuZXJzJmNvcm5lci1yYWRpdXM9OCZiZz1GRkZGRkYmYm9yZGVyPTIlMkNGRkZGRkYmZm09cG5nMzImcz1mNzNmZmY3YmI1YjY4ZWU2YmQ0MmMzN2JlZjJhNWJhNA%26mark-x%3D186%26mark-y%3D515%26mark-w%3D40%26mark-h%3D40%26s%3D7b72fa82b6f6f7185ce42e9e9d4b1a0b?ixlib=rb-4.1.1&amp;amp;w=1200&amp;amp;fm=jpg&amp;amp;mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjEuMSZ3PTk2MCZoPTMyNCZ0eHQ9JUUzJTgxJUFBJUUzJTgxJTlDJUUzJTgwJTgxJUU3JUI1JTg0JUU3JUI5JTk0JUUzJTgxJUFFJUUzJTgxJUE0JUUzJTgxJThGJUUzJTgyJThBJUUzJTgxJUE4JUUzJTgyJUJEJUUzJTgzJTk1JUUzJTgzJTg4JUUzJTgyJUE2JUUzJTgyJUE3JUUzJTgyJUEyJUUzJTgyJUEyJUUzJTgzJUJDJUUzJTgyJUFEJUUzJTgzJTg2JUUzJTgyJUFGJUUzJTgzJTgxJUUzJTgzJUEzJUUzJTgxJUFGJUU0JUJDJUJDJUUzJTgxJUE2JUUzJTgxJTk3JUUzJTgxJUJFJUUzJTgxJTg2JUUzJTgxJUFFJUUzJTgxJThCJnR4dC1hbGlnbj1sZWZ0JTJDdG9wJnR4dC1jb2xvcj0lMjMzQTNDM0MmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9NTYmdHh0LXBhZD0wJnM9MWY4M2U4Y2NiNzc3YTQxNDRhMmU1ZDEyM2ExMWE0MmQ&amp;amp;mark-x=120&amp;amp;mark-y=112&amp;amp;blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjEuMSZ3PTgzOCZoPTU4JnR4dD0lNDBoaXJva2lkYWljaGkmdHh0LWNvbG9yPSUyMzNBM0MzQyZ0eHQtZm9udD1IaXJhZ2lubyUyMFNhbnMlMjBXNiZ0eHQtc2l6ZT0zNiZ0eHQtcGFkPTAmcz02YmQwMDcxMTBmZTI0NDRhYTg1YTZlZGYzYjljOTAyNQ&amp;amp;blend-x=242&amp;amp;blend-y=454&amp;amp;blend-w=838&amp;amp;blend-h=46&amp;amp;blend-fit=crop&amp;amp;blend-crop=left%2Cbottom&amp;amp;blend-mode=normal&amp;amp;txt64=5qCq5byP5Lya56S-UmVjdG9y&amp;amp;txt-x=242&amp;amp;txt-y=539&amp;amp;txt-width=838&amp;amp;txt-clip=end%2Cellipsis&amp;amp;txt-color=%233A3C3C&amp;amp;txt-font=Hiragino%20Sans%20W6&amp;amp;txt-size=28&amp;amp;s=5c50fc4dd1a2ac948cd1f2fbafc58f22&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://qiita.com/hirokidaichi/items/d12fcce80ee593bcf34d&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;なぜ、組織のつくりとソフトウェアアーキテクチャは似てしまうのか - Qiita&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;このエントリーは、Engineering Manager Advent Calendarの25日目、最終日の記事です。 はじめに 拙著「エンジニアリング組織論への招待」では、ソフトウェア自体の構造とソフトウェアを作り上げる組織の構造が似てしまうという「コンウェイの法則」に...&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;また一言添えておくと､アーキテクチャを決めると単にコミュニケーションが減るのではなく､ &lt;em&gt;不要な&lt;/em&gt; コミュニケーションがなくなるだけだ｡
デプロイ可用性やテスト容易性などを強く指向するアーキテクチャならば､SREやQAエンジニアとの連携が必要になるだろう｡
ただそれはアプリケーションやプロダクトの運用に対し &lt;em&gt;本質的な&lt;/em&gt; コミュニケーションなので､減ることも減らす必要もない｡&lt;/p&gt;&lt;hr&gt;&lt;p&gt;ブログ内で何の言及もしていなかったがコメントが追加された｡
GitHub sponsorも始めた｡
&lt;a href=&quot;https://github.com/sponsors/Nymphium&quot;&gt; いいから黙って俺に投資しろ &lt;/a&gt;｡&lt;/p&gt;&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;

&lt;li id=&quot;fn1&quot;&gt;
&lt;p&gt;この記事は11月26日に執筆を開始した &lt;a href=&quot;#fnref1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn2&quot;&gt;
&lt;p&gt;Mark Seemann. &lt;a href=&quot;https://www.amazon.co.jp/%E8%84%B3%E3%81%AB%E5%8F%8E%E3%81%BE%E3%82%8B%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9-%E2%80%95%E8%A4%87%E9%9B%91%E3%81%95%E3%82%92%E9%81%BF%E3%81%91%E6%8C%81%E7%B6%9A%E5%8F%AF%E8%83%BD%E3%81%AB%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E7%B5%8C%E9%A8%93%E5%89%87%E3%81%A8%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF-Mark-Seemann/dp/4814400799/ref=sr_1_1?crid=2K28RS1AI38B9&amp;amp;dib=eyJ2IjoiMSJ9.EWSgA81PTYyI8I0JIUwnFjYiwim78aWobkWw9p2RGnFPLAsmRIH9wD90zF1ZK1si0Ere0TNNsdEq702-OAASmABfdyab5hKOJkOX12fcWkTMHEBAdSmYlzacAQ75BYAaqdqHX8LRKz6NO8hoKlWGAZ9UTJWfR8TfdPwcN9sSh9VO_lx3ypWS2WtkcB5fPChM7L7NGmfORUB6RcVBuaELAfYfNuziUTICKW9RjjdRJzMyhIX5CC1rrEcCRgrCGjl9qvBSQJJ8-S0SYaVxjB9JP0PqPyCFv9A22apiJxvyPTI.J_a2MSS7hiQx-6pAQn--KtNCUxhfKRCnsylvVR5ui_w&amp;amp;dib_tag=se&amp;amp;keywords=%E8%84%B3%E3%81%AB%E5%8F%8E%E3%81%BE%E3%82%8B%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9&amp;amp;qid=1764498518&amp;amp;sprefix=%E8%84%B3%E3%81%AB%E5%8F%8E%E3%81%BE%E3%82%8B%2Caps%2C201&quot;&gt;『脳に収まるコードの書き方』&lt;/a&gt;. オライリー･ジャパン. 2024. 長年の経験に裏打ちされた著者なりのプログラミング哲学や著名人からの学びが､example projectを作る過程でつらつらと述べられている｡ページを捲るたびにハッとすることが多い｡良書 &lt;a href=&quot;#fnref2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn3&quot;&gt;
&lt;p&gt;Mark Richards, Neal Ford. &lt;a href=&quot;https://www.amazon.co.jp/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%E3%81%AE%E5%9F%BA%E7%A4%8E-%E2%80%95%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E5%9F%BA%E3%81%A5%E3%81%8F%E4%BD%93%E7%B3%BB%E7%9A%84%E3%82%A2%E3%83%97%E3%83%AD%E3%83%BC%E3%83%81-Mark-Richards/dp/4873119820/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;amp;crid=1JWPVRUTI7QXA&amp;amp;dib=eyJ2IjoiMSJ9.CgHOWtRJ2b97qIZKH5QGOIn2eXBSs8M0atibVRTn35cYel6sZqp0JYNETghKXEGCNHMYvvD4QsjVAeFKZeq6oW7i96IsB1KoB8a7AW9MvxkcnhMbQdqS-qCRalVYLaVlYjI78jMak5Ib337Do5QiNvFDSLG-SFM3brv1uUxKohiZNgWVpN6KElOGaHkGBOrIOnGI3jK5b8coRSlhq9uwv6yyjqLrwSHxrKePSCfZ6zxHlp_0iqnLtK5TXDuoUzu7pJA5TE5oTbo-hOu29SIhGhoupTxw-qctSqUIePU34l0.nr2JO45uwBCKkZWE9Yzo7Om7fpTWAG6DZ8YdvGtCVtc&amp;amp;dib_tag=se&amp;amp;keywords=%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3&amp;amp;qid=1764575171&amp;amp;sprefix=%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3%2Caps%2C176&amp;amp;sr=8-2&quot;&gt;『ソフトウェアアーキテクチャの基礎』&lt;/a&gt;. オライリージャパン. 2022. やりたいこと､できることに応じたソフトウェアアーキテクチャが並んでいる｡アーキテクチャを考えるにあたっての指標も並んでおり､どこを目指せばよいかも考えられるし現状の診断もできるようになる &lt;a href=&quot;#fnref3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn4&quot;&gt;
&lt;p&gt;著者調べ &lt;a href=&quot;#fnref4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn5&quot;&gt;
&lt;p&gt;&lt;em&gt;本当に&lt;/em&gt; 単純な場合に限る &lt;a href=&quot;#fnref5&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 14 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://nymphium.github.io/2025/12/14/ddd.html</link>
        <guid isPermaLink="true">https://nymphium.github.io/2025/12/14/ddd.html</guid>
        
        <category>DDD</category>
        
        <category>ソフトウェアアーキテクチャ</category>
        
        
      </item>
    
      <item>
        <title>特に旬とかではないベストテン</title>
        <enclosure type="image/png" length="0" url="https://nymphium.github.io/pictures/github_icon.png"></enclosure>
        <description>&lt;h1 id=&quot;%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;はじめに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;季節感 なし&lt;/p&gt;&lt;p&gt;脈絡 なし&lt;/p&gt;&lt;p&gt;思い出補正 あり&lt;/p&gt;&lt;p&gt;突然のおすすめ楽曲発表ドラゴンに成ったんで､発表します｡
オールジャンルすぎておすすめ感はない&lt;/p&gt;&lt;h1 id=&quot;10%E4%BD%8D+Carbon-based+Anatomy+-+Cynic&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#10%E4%BD%8D+Carbon-based+Anatomy+-+Cynic&quot;&gt;10位 Carbon-based Anatomy - Cynic&lt;/a&gt;&lt;/h1&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=lY43tiG7jBU&amp;amp;list=OLAK5uy_mbUe15rd5o1Kq2ejtBA6CNAbSLRP4H9Hc&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=lY43tiG7jBU&amp;amp;list=OLAK5uy_mbUe15rd5o1Kq2ejtBA6CNAbSLRP4H9Hc&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;狂気と美しさを感じるプログレッシブバンドCynicのアルバム｡
そうベストテンと言いつついきなりアルバムですね｡
『Admist The Coals』の重く複雑な入りから『Box Up My Bones』で突き抜ける感じがたまらん｡
Cynicの他の曲だと『I&apos;m a but wave to …』が狂おしくすき｡&lt;/p&gt;&lt;h1 id=&quot;9%E4%BD%8D+%E7%9B%AE%E3%81%8C%E6%98%8E%E3%81%8F%E8%97%8D%E8%89%B2+-+%E3%82%B5%E3%82%AB%E3%83%8A%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#9%E4%BD%8D+%E7%9B%AE%E3%81%8C%E6%98%8E%E3%81%8F%E8%97%8D%E8%89%B2+-+%E3%82%B5%E3%82%AB%E3%83%8A%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3&quot;&gt;9位 目が明く藍色 - サカナクション&lt;/a&gt;&lt;/h1&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Xcj-SVs31cQ&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Xcj-SVs31cQ&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;今好きになれる日本のロックバンドってあるんだと思った｡
Queenの『Bohemian Rhapsody』を初めてちゃんと聴いたときと同じ衝撃､いやそれ以上があった｡
日本のロックシーンでこういうのやってくれるんだとか､サカナクションでもキャッチーな『新宝島』などがある中でも依然人気であることに､なんつうかこういう楽曲がちゃんと評価される土壌があることに嬉しさを感じたりとか…｡
『ミュージック』もかなり甲乙つけがたい｡&lt;/p&gt;&lt;h1 id=&quot;8%E4%BD%8D+%E5%85%89%E3%81%AE%E8%9E%BA%E6%97%8B%E5%BE%8B+-+Kukui&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#8%E4%BD%8D+%E5%85%89%E3%81%AE%E8%9E%BA%E6%97%8B%E5%BE%8B+-+Kukui&quot;&gt;8位 光の螺旋律 - Kukui&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;爆思い出補正｡ローゼンメイデン2期ED｡
霜月はるかが好きというか､ローゼンメイデンのエンディングで好きになったね｡
アニオリの薔薇水晶とかいう謎キャラがいたが､謎キャラ込みでスループットがあり､曲と合わせて良いですね｡
チェンバロっぽいキーボードと明るくも静謐な旋律がサァ! 翠星石がなあ!!!
2サビ後半の実質テンポアップと間奏のサビと霜月はるかっぽいコーラスで最後まで突き抜けたあとスンッとなる終わりが気持ちいい｡&lt;/p&gt;&lt;h1 id=&quot;7%E4%BD%8D+%E3%82%BB%E3%83%B3%E3%83%86%E3%82%A3%E3%83%95%E3%82%A9%E3%83%AA%E3%82%A2+-+Ceui&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#7%E4%BD%8D+%E3%82%BB%E3%83%B3%E3%83%86%E3%82%A3%E3%83%95%E3%82%A9%E3%83%AA%E3%82%A2+-+Ceui&quot;&gt;7位 センティフォリア - Ceui&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;爆思い出補正2｡青い花ED｡
理由はないけど聴いてると涙が出ます｡
アニオリの終わり方もかなり好き｡
あーちゃんは泣き虫なんですなぁ…｡&lt;/p&gt;&lt;h1 id=&quot;6%E4%BD%8D+Birdland+-+Weather+Report&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#6%E4%BD%8D+Birdland+-+Weather+Report&quot;&gt;6位 Birdland - Weather Report&lt;/a&gt;&lt;/h1&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=SvhmaNlLgRM&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=SvhmaNlLgRM&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;実はわたくしベースを弾くのが趣味なんですが､ベースが好きになった一曲｡
だがいきなり最初からハーモニクスでおおよそ普通の(?)ベースらしからぬ高い音が出てくる｡
ベースが好きな曲なら他にもLiquid Tension Experimentの『Acid Rain』とかMr. Bigの『Addicted To That Rush』とかあるが､ベストテンに挙げるならやはりこの曲か｡&lt;/p&gt;&lt;h1 id=&quot;5%E4%BD%8D+COSMIC+LOVE+-+%E6%B0%B4%E6%A8%B9%E5%A5%88%E3%80%85&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#5%E4%BD%8D+COSMIC+LOVE+-+%E6%B0%B4%E6%A8%B9%E5%A5%88%E3%80%85&quot;&gt;5位 COSMIC LOVE - 水樹奈々&lt;/a&gt;&lt;/h1&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=-vbKabIRv9U&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=-vbKabIRv9U&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;大学受験のあたりで水樹奈々を謎に聴きまくっていたが最も耳に残っている一曲｡
これも思い出補正すか?
サビのメロディの運びが面白い｡
実は『Innocent Starter』もBメロ～サビのつなぎあたりが同じくらい面白い｡&lt;/p&gt;&lt;h1 id=&quot;4%E4%BD%8D+True+-+L%27Arc~en~Ciel&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#4%E4%BD%8D+True+-+L%27Arc~en~Ciel&quot;&gt;4位 True - L&apos;Arc~en~Ciel&lt;/a&gt;&lt;/h1&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=-z3zJIA8gxM&amp;amp;list=OLAK5uy_lVGp6u-CXZv6flYYGWzf_W6SRsL9suQLU&amp;amp;index=1&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://i.ytimg.com/vi/-z3zJIA8gxM/maxresdefault.jpg&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=-z3zJIA8gxM&amp;amp;list=OLAK5uy_lVGp6u-CXZv6flYYGWzf_W6SRsL9suQLU&amp;amp;index=1&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Fare Well&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Provided to YouTube by Sony Music Labels Inc.Fare Well · L&apos;Arc-en-CielTrue℗ 1996 Sony Music Labels Inc.Released on: 2012-11-07Associated Performer, Arranger:...&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;実は2005年くらいまでのラルクがだいたいすきで､中でも思い入れ深いアルバム｡
前アルバム収録の『Vivid Colors』の爽やかさに厚みをかけた『風にきえないで』などバンドとしての洗練も感じられる｡
頭から終わりまでバラエティに富んだ1枚となっており､なんといっても最後の『Dearest Love』が…ええな｡
6曲目の『The Fourth Avenue Cafe』といえばるろ剣ですが､『Dearest Love』を聴いて勝手に星霜編を思い出して勝手に気分がよくなってしまう｡
9曲目の『I wish』のあたたかい冬感から一転して真冬のような冷たさ(雪国出身並感)が､たまらん&lt;/p&gt;&lt;h1 id=&quot;3%E4%BD%8D+The+Nightfly+-+Donald+Fagen&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#3%E4%BD%8D+The+Nightfly+-+Donald+Fagen&quot;&gt;3位 The Nightfly - Donald Fagen&lt;/a&gt;&lt;/h1&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Ueivjr3f8xg&amp;amp;list=OLAK5uy_kJmuqJb6DRctnv0NEBJNkhfwy8aSqrYA8&amp;amp;index=2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Ueivjr3f8xg&amp;amp;list=OLAK5uy_kJmuqJb6DRctnv0NEBJNkhfwy8aSqrYA8&amp;amp;index=2&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;カッコ良すぎる…｡
かっこいい音をちゃんと配置するとこうなるかのような完成度｡
中でも1曲目の『I.G.Y.』がやはり至高…イントロかっこよすぎだろ｡これを聴きながら都会の夜を歩きたすぎだろ｡&lt;/p&gt;&lt;h1 id=&quot;2%E4%BD%8D+Metropolis+Part+2%3A+Scene+from+a+memory+-+Dream+Theater&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2%E4%BD%8D+Metropolis+Part+2%3A+Scene+from+a+memory+-+Dream+Theater&quot;&gt;2位 Metropolis Part 2: Scene from a memory - Dream Theater&lt;/a&gt;&lt;/h1&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=H2UHWFU5uFY&amp;amp;list=OLAK5uy_mY0UJ7SdDG7n4DgXGJ_h-vG0QH9LpayaA&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=H2UHWFU5uFY&amp;amp;list=OLAK5uy_mY0UJ7SdDG7n4DgXGJ_h-vG0QH9LpayaA&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;高校の修学旅行の自由時間でCDショップに行き即ホテルに戻ってこのアルバムを聴きながらベッドで涙を流しつつ就寝た思い出の一枚｡
同室だった相馬くんはDinosaur Jr.を聴いていた｡&lt;/p&gt;&lt;p&gt;コンセプトアルバムの最高峰｡
アルバムを再生すると物語を追体験することになる｡
1､2曲目の物語に吸い込まれていくようなイントロダクションから『Strange Deja Vu』の結末を予告するような少し切ないのに爽やかな勢いの乗ったサビが､すごーい…
そのまま物語が怒涛のDream Theaterワールドの上で展開して映画のラストシーンのようなクライマックスの『Finally Free』に至り､茫然自失となる｡
この物語の1つ前にあたる『Metropolis Part 1: The Miracle and the Sleeper』もすごい｡
すごいっつうか意味わからん｡&lt;/p&gt;&lt;h1 id=&quot;1%E4%BD%8D+%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC%E3%82%AC%E3%83%BC%E3%83%AB+-+%E3%82%8F%E3%81%8B%EF%BD%A5%E3%81%B5%E3%81%86%E3%82%8A%EF%BD%A5%E3%81%99%E3%81%AA%E3%81%8A&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#1%E4%BD%8D+%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC%E3%82%AC%E3%83%BC%E3%83%AB+-+%E3%82%8F%E3%81%8B%EF%BD%A5%E3%81%B5%E3%81%86%E3%82%8A%EF%BD%A5%E3%81%99%E3%81%AA%E3%81%8A&quot;&gt;1位 カレンダーガール - わか･ふうり･すなお&lt;/a&gt;&lt;/h1&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=B4NhvHuvfTI&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=B4NhvHuvfTI&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;すまんやけど｡
アイカツ1期ED｡
この一曲には星宮いちごさんが大スター宮になるまでの重みがあってですね｡
グルーヴィなサウンドでABメロノリノリなんだけどサビメロが少し切ない入りで､だけど最後はパッとなる構成｡
しかしてサビの&quot;何てコトない毎日が かけがえないの オトナはそう言うけれど いまいちピンとこないよ&quot;って､なんや…😭
1期にして早くもそれぞれの道を歩んでいくのを予見するようなセツナメロディ､でもそれを跳ね飛ばす元気さや若さ､まだフツーの女の子感｡
俺って元アイドルじゃないんだけど､幼少期に仲良かったけど疎遠になった友達や何者でもないバカガキで遊んでいた頃を思い出さずにはいられない｡
そしてまさに宝ものになるなんてことない毎日を駆け抜けている(た)彼女たちが歌うんだよね､&quot;いまいちピンとこないよ&quot;って｡
&quot;思い出は未来のなかに&quot;ってなんですかあおいさん?! 情緒がおかしくなっちまうよ…｡&lt;/p&gt;&lt;h1 id=&quot;%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;おわりに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;最近はぜんぜん若モンの曲しか聴いてない｡え､メタル?(笑)
5年後くらいに発表してたらWaMiとか明透とか東雪蓮が入っていたかもしれない｡&lt;/p&gt;&lt;p&gt;KMNZが楽曲として完成度が高くてビビる｡
こん人らここにきてコーラスで攻める曲を出せるのかよ｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=MehG9Ms8ygU&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=MehG9Ms8ygU&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;また､電音部が音楽×ストーリーで展開しているが楽曲がバッチリはまっててすごい!
『月読のダンス』がやばいですね～とか『ルララルララ』のリミックスの仕方とか､やるな…w&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=nrieZWF3TCg&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=nrieZWF3TCg&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;曲作りが上手いですね～とんでもない量の曲を作ってくれてありがとう電音部&lt;/p&gt;&lt;hr&gt;&lt;p&gt;ということで来年2月にDream Theaterが来日するらしいんで行きますわよ～～～(完)&lt;/p&gt;</description>
        <pubDate>Sat, 06 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://nymphium.github.io/2025/12/06/%E7%89%B9%E3%81%AB%E6%97%AC%E3%81%A8%E3%81%8B%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%84%E3%83%99%E3%82%B9%E3%83%88%E3%83%86%E3%83%B3.html</link>
        <guid isPermaLink="true">https://nymphium.github.io/2025/12/06/%E7%89%B9%E3%81%AB%E6%97%AC%E3%81%A8%E3%81%8B%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%84%E3%83%99%E3%82%B9%E3%83%88%E3%83%86%E3%83%B3.html</guid>
        
        <category>雑感</category>
        
        
      </item>
    
      <item>
        <title>OCaml 5.4のlabeled tuples調査隊 ～名前の力を感じろ～</title>
        <enclosure type="image/png" length="0" url="https://nymphium.github.io/pictures/github_icon.png"></enclosure>
        <description>&lt;p&gt;こんにちは､びしょ～じょです｡&lt;/p&gt;&lt;p&gt;PoE2パッチ0.3のアビサルもエンドゲームTier15到達したら急に飽きました｡
アクトランに関しては､新たに追加されたAct4は島々を船で回る楽しさや(Act3と比較して)移動の簡単さなどでけっこうすき｡
一方結局セケマとアルティメイタムがくだらんすぎるんですわな…｡
というのとアビサルでエグいDotを敷いてブリンクで粘着してくるmodがありえない話し! ブリンクにブリンクで合わせてdotから抜ければいいんだけど大量にmobがいて当たり判定があるんでブリンクアウトも少しむずいため確死があってさぁ～!
でも棘タイタンは面白かったです｡問題点はタイタンというジョブが単純に弱く､vs単体が特に弱いんでアクトボスで10分くらい盾を構えるだけの緊張感のない間延びした戦いを過ごす部分｡
安定感はすごい｡&lt;/p&gt;&lt;p&gt;ということでEscape From Duckovを始めたんですがこれはイイネ｡
本家EFTのPvP(vE)ゆえのスキルツリーやハイドアウト育成テンポの遅さはうまく解消されつつ漁る楽しさや難易度調整によるカジュアルから本家のハラハラまでいろんなプレイヤーに合わせたレンジの広さ､いいですねえ｡
ハイドアウトのチルいBGMも良い｡ あとは本家のようないろんなモーションにリアルサウンドがついてくるとおもろいやろなぁと思いつつもカートゥーン世界観にどれくらい合うんかなとも…現時点ですでにおもろいんでこっからブラッシュアップされて更に神ゲーになると嬉しい｡
確かにこれでPvPもしたいけど､先述のとおり今のテンポ感だと本家以上にギャップのあるマッチが生まれそうなんで､難しいね｡&lt;/p&gt;&lt;h1 id=&quot;1.+%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#1.+%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;1. はじめに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;OCaml5.4が最近リリースされた｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://ocaml.org/releases/5.4.0#whats-new&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://ocaml.org/_/MWIyY2ZmMWM5YzdkYWNmYWI4NGQ0MDBjOGFiZTYxOTg/ocaml_org_social_media.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://ocaml.org/releases/5.4.0#whats-new&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;OCaml 5.4.0 Release Notes&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;OCaml 5.4.0 was released on 2025-10-09. Learn more about this in the release notes.&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;今回のリリースでも多くの改善や新機能が追加されたが､本記事ではその中から &lt;strong&gt;labeled tuples&lt;/strong&gt; に焦点を当てる｡&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://ocaml.org/manual/5.4/labeledtuples.html&quot;&gt;公式ドキュメントはこちら&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;1-1.+%E6%9C%80%E5%88%9D%E3%81%AB%E3%83%8D%E3%82%BF%E3%83%90%E3%83%AC&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#1-1.+%E6%9C%80%E5%88%9D%E3%81%AB%E3%83%8D%E3%82%BF%E3%83%90%E3%83%AC&quot;&gt;1-1. 最初にネタバレ&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;ごちゃごちゃ書いていくが､端的に申し上げるとこういったことが書けて嬉しい｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;便利&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;analyze_list&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lst&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;min&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fold_left&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;min&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max_int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lst&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fold_left&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;min_int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lst&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fold_left&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lst&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lst&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;avg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;float_of_int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;float_of_int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;avg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;avg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;analyze_list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Min: %d, Max: %d, Avg: %f&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;min&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;avg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;関連する値をタプルで返す場面は多い｡
しかし､返ってきたタプルの1番目の要素は何だっけ､2番目は…？と､順序をいちいち覚えたり､ドキュメントを確認したりする必要があったりと､どのアドレスが何を意味するのかパッと分からんことがある｡
かといって､そのためだけにrecordで新たに型を定義するのも少し…｡
というときにlabeled tuplesが役に立つ｡&lt;/p&gt;&lt;p&gt;またADTsの引数にももちろん利用できる｡
特にGADTsを用いて柔軟なinterpreter patternを実装する際､これまでは引数にラベルを付けられず､少し可読性に欠けることがあったが､labeled tuplesでエレガントに表現できる｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CreateUser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FindUser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;option&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;interpret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CreateUser&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FindUser&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;名前という&lt;strong&gt;追加の意味を値に付けられる&lt;/strong&gt;ということですよこれは｡
名前があるって大変うれしいね｡
名前といえばローゼンメイデンで蒼星石さんが名前は何でも良いがついてると嬉しいという内容のシーンが好きなんですが&lt;sup id=&quot;fnref1&quot; title=&quot;『Rosen Maiden』 Phase 28 &quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;､今はもう令和か｡&lt;/p&gt;&lt;h1 id=&quot;2.+%E3%81%B5%E3%81%A4%E3%83%BC%E3%81%AEtuples%E3%81%A8%E3%81%AE%E5%B7%AE%E5%88%86%E3%82%92%E8%A6%8B%E3%82%8B&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2.+%E3%81%B5%E3%81%A4%E3%83%BC%E3%81%AEtuples%E3%81%A8%E3%81%AE%E5%B7%AE%E5%88%86%E3%82%92%E8%A6%8B%E3%82%8B&quot;&gt;2. ふつーのtuplesとの差分を見る&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;まずは小手調べ｡
基本的な構文とこれまでのunlabeled tuplesとの違いを見ていく｡
お手元のutopを起動して､一緒に試してみてください｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;c&quot;&gt;(* リテラルの確認 *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* ラベルなしの要素とも混在可能 *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hoge&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hoge&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;型が&lt;code&gt;x:int * y:int&lt;/code&gt;となっており､&lt;code&gt;int * int&lt;/code&gt;とは区別されている｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;みんなちがってみんないい&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;was&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
       &lt;span class=&quot;nc&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;was&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;was&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
       &lt;span class=&quot;nc&quot;&gt;Labels&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;false&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* destructuring assignmentも同様 *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;was&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;
       &lt;span class=&quot;nc&quot;&gt;The&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tuple&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labeled&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unlabeled&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;was&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;ラベル多相とかsubtypingはなさそう&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;まあtuplesにもサイズに関してsubtypingないし&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subtype&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;当然型名にも束縛できるし多相も使える&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;関数の引数にも驚きなく使える&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;単なるsyntacticな拡張ではなく､型レベルで組み込まれた新機能ということが分かる｡&lt;/p&gt;&lt;h1 id=&quot;3.+%E9%96%A2%E6%95%B0%E3%81%AE%E3%83%A9%E3%83%99%E3%83%AB%E4%BB%98%E3%81%8D%E5%BC%95%E6%95%B0%E3%81%A8%E9%9B%B0%E5%9B%B2%E6%B0%97%E4%BC%BC%E3%81%A6%E3%81%BE%E3%81%99%E3%81%8C&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#3.+%E9%96%A2%E6%95%B0%E3%81%AE%E3%83%A9%E3%83%99%E3%83%AB%E4%BB%98%E3%81%8D%E5%BC%95%E6%95%B0%E3%81%A8%E9%9B%B0%E5%9B%B2%E6%B0%97%E4%BC%BC%E3%81%A6%E3%81%BE%E3%81%99%E3%81%8C&quot;&gt;3. 関数のラベル付き引数と雰囲気似てますが&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;たしカーニハン｡
ただ明確な違いとしては､ラベル付き引数には順序がない一方､先述のとおりlabeled tuplesにはある｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;c&quot;&gt;(* ラベル付き引数は順不同 *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListLabels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fold_left&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListLabels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fold_left&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* 再掲 *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;was&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
       &lt;span class=&quot;nc&quot;&gt;Labels&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また､ラベル付き引数の特徴であるオプショナル引数(&lt;code&gt;?arg&lt;/code&gt;)もlabeled tuplesにはない｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;c&quot;&gt;(* ラベル付き引数のoptional引数 *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* まあ意味分からんですわな *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Syntax&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&quot;https://ocaml.org/manual/5.4/labeledtuples.html#sss:labledtuples-limitations&quot;&gt;公式マニュアルのlimitationの項&lt;/a&gt;にもラベル付き引数との曖昧性に関する言及がある｡&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;Parentheses are necessary to disambiguate functions types with labeled arguments from function types with labeled tuple arguments when the first element of the tuple has a label.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;あっ逆に関数の引数以外ではカッコ省略できるんだ&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;そうなんだ&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* 関数定義で括弧を省略するとラベル付き引数と解釈されて構文エラー *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Syntax&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* カッコヨシ! *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h1 id=&quot;4.+Records%E3%82%88%E3%82%8A%E4%BD%BF%E3%81%84%E5%8B%9D%E6%89%8B%E3%81%84%E3%81%84%E3%82%93%E3%81%A7%E3%81%99%E3%81%8B%E3%81%A3%E3%81%A6%E3%81%AD&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#4.+Records%E3%82%88%E3%82%8A%E4%BD%BF%E3%81%84%E5%8B%9D%E6%89%8B%E3%81%84%E3%81%84%E3%82%93%E3%81%A7%E3%81%99%E3%81%8B%E3%81%A3%E3%81%A6%E3%81%AD&quot;&gt;4. Recordsより使い勝手いいんですかってね&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;類似の機能にrecordがあるやん｡
Recordsは型-モジュール(名前空間)に束縛されるが､labeled tuplesは自由なところが個人的に大きなポイントに感じる｡&lt;/p&gt;&lt;p&gt;Recordsは基本的に名前がついており&lt;sup id=&quot;fnref2&quot; title=&quot;Variantのフィールドは無名といえば無名だが､variantの名前空間には紐づいてる &quot;&gt;&lt;a href=&quot;#fn2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;､名前があるということは名前空間に属するということ｡
しかし､labeled tuplesはそうした制約から自由｡定義なしにアドホックに作ることができる｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;c&quot;&gt;(* Recordは型を定義する必要がある *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* Recordの名前空間は実は推論してくれるんですが､この文脈では失敗する *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Unbound&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* ので明示的に名前空間Mを教える *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* 一方labeled tuplesは自由に作られる *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* 異なるモジュール間でも構造が合っていればOK *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;N&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;N&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;手軽でイイネ｡&lt;/p&gt;&lt;p&gt;一方､recordsのフィールドには順序がないが､先述の通りlabeled tuplesには順序があるなどの取り回しずらさはある｡
加えて､recordsのフィールド省略やprojectionといった操作もない｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;c&quot;&gt;(* おさらいレコード *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* ちょっとかゆい使い勝手の悪さ *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&apos;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;which&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* あっそういう推論になって型検査が通らなくなるんですね *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;The&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&apos;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;was&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
       &lt;span class=&quot;nc&quot;&gt;The&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tuple&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labeled&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unlabeled&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;was&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;(* なのでこちらはOK *)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ランタイムの表現としてはいずれもn-length arrayなんで同じような操作感だと嬉しいニャンけどねえ
&lt;code&gt;Obj&lt;/code&gt;で中身を見てみよう｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/ocaml/ocaml-original.svg&quot; alt=&quot;ocaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;ランタイム上は同じ&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;repr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flip&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;repr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flip&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;おんなじやおんなじやおもて…この操作の不便さを…変えてほしい…!!&lt;/p&gt;&lt;h1 id=&quot;5.+%E7%B7%8F%E8%A9%95&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#5.+%E7%B7%8F%E8%A9%95&quot;&gt;5. 総評&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;器用貧乏だけど入ったことが嬉しいんで､嬉しいね｡
実は順序なしだとpolymorphic variantsで代替できる気がする(互換性は未検証)&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`X&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Y&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`X&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Y&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`X&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Y&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;まあこっちのがランタイムコストちょっとかさむとか記述量がアレソレとかあるんで､一応優位性はね｡
ただADTsの引数については無名record書けるんやった～w&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CreateUser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FindUser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;option&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;まあ関数の戻り値に自然に名前をつけられるのはかなり良い｡&lt;/p&gt;&lt;h1 id=&quot;6.+%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#6.+%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;6. おわりに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;いろんな言語機能が入ると嬉しいです｡嬉しいなあ｡
&lt;a href=&quot;https://github.com/ocaml/ocaml/pull/13275&quot;&gt;Modular explicits&lt;/a&gt;が5.5に入りそうな気配があったりなかったりするんで､次のリリースも期待大です｡&lt;/p&gt;&lt;p&gt;ここで書く場所がなかったんで供養したい唐突なOCamlトリビア: ocaml/ocamlのtuplesは最大$2^{22}-1$個の要素を持てる&lt;sup id=&quot;fnref3&quot; title=&quot;https://ocaml.org/manual/5.4/values.html#ss%3Avalues%3Atuple さっき知った｡recordsも同じランタイム表現なので2^22-1個のフィールドを持てる &quot;&gt;&lt;a href=&quot;#fn3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;｡&lt;/p&gt;&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;

&lt;li id=&quot;fn1&quot;&gt;
&lt;p&gt;『Rosen Maiden』 Phase 28 &lt;a href=&quot;#fnref1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn2&quot;&gt;
&lt;p&gt;Variantのフィールドは無名といえば無名だが､variantの名前空間には紐づいてる &lt;a href=&quot;#fnref2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn3&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://ocaml.org/manual/5.4/values.html#ss%3Avalues%3Atuple&quot;&gt;https://ocaml.org/manual/5.4/values.html#ss%3Avalues%3Atuple&lt;/a&gt; さっき知った｡recordsも同じランタイム表現なので2^22-1個のフィールドを持てる &lt;a href=&quot;#fnref3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 26 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://nymphium.github.io/2025/10/26/ocaml54-labelledtuples.html</link>
        <guid isPermaLink="true">https://nymphium.github.io/2025/10/26/ocaml54-labelledtuples.html</guid>
        
        <category>OCaml</category>
        
        
      </item>
    
      <item>
        <title>関数型まつり2025ありがとう､そして補足</title>
        <enclosure type="image/png" length="0" url="https://nymphium.github.io/pictures//2025/06/17/fpmatsuri-ty/thumb.png"></enclosure>
        <description>&lt;p&gt;こんにちは､びしょ〜じょです｡&lt;/p&gt;&lt;p&gt;ナイトレインは買ったら最後資料が作れなくなると思って発表終わるまで買うまいとしていたんですが､結局LoLのブロウルを無限にやってました｡
ショウジンTF黒斧のファイタールシアンが面白いですが､ナヴォリ積むならショウジンじゃなくてIEでよくないか? と思わなくもない｡
今ならポーションで無限スケールするので､天啓で金策ビルドも良いかもしれない｡
みんなのブロウル用クソビルドはどうかな?&lt;/p&gt;&lt;hr&gt;&lt;h1 id=&quot;%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;はじめに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;https://2025.fp-matsuri.org/&quot;&gt;関数型まつり2025&lt;/a&gt;にスピーカーおよびスポンサーとして参加した｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://nymphium.github.io/pdf/fp_matsuri_2025.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://nymphium.github.io/pdf/fp_matsuri_2025.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://nymphium.github.io/pdf/fp_matsuri_2025.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Continuations: continued and to be continued - lilyum ensemble&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;lily, Aikatsu, Programming language, and more&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;とりあえず発表すると人から声を掛けてもらえるのと､他の発表者に声を掛けやすいという雑なモチベで応募した｡
ちゅうか関数型というある程度話す内容のあるドメインではあるし｡
スライド作るのが､ジジイになって馬力や集中力が減り､当日発表30分前まで泣きながら作るという激ヤバだったんですが､とりあえず情報を詰め込むという発表においてはアンチパターン寄りな方向でバリューを出しにいった｡&lt;/p&gt;&lt;h2 id=&quot;%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B5%E3%83%BC%E3%83%96%E3%83%BC%E3%82%B9&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B5%E3%83%BC%E3%83%96%E3%83%BC%E3%82%B9&quot;&gt;スポンサーブース&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;ブースに来てくれた方々にも話したが､弊社は積極的に関数型言語を使っているわけではなく､&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;び｢これどうすか? プロポーザルも一応投げているが｣ &lt;/li&gt;
&lt;li&gt;社｢関数型明るくないけど採択されたらいいですよ｣&lt;/li&gt;
&lt;li&gt;→採択された&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;という流れでスポンサー出展が決まった｡
そもそも&lt;a href=&quot;https://note.com/eiicon/n/nd8df6784778d&quot;&gt;PPLにもスポンサーしていた&lt;/a&gt;ので､社内での出展ハードルはそんなに高くはなかったんですが､よかったですね｡&lt;/p&gt;&lt;p&gt;自転車置き場の議論のように誰でも参加できる､さらにインタラクションのある催しをしたいなと思ってたんで､仕事で書きたい言語にシールを貼ってもらうというアクティビティをした｡&lt;/p&gt;&lt;div class=&quot;enclosed-tweet&quot; align=&quot;center&quot;&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;
&lt;p lang=&quot;ja&quot; dir=&quot;ltr&quot;&gt;関数型まつり &lt;a href=&quot;https://x.com/hashtag/fp_matsuri?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#fp_matsuri&lt;/a&gt; 全日程終了！&lt;br&gt;株式会社eiicon開発部として初めての出展でしたが、大きな刺激をいただける2日間でした。&lt;br&gt;運営の皆様、また弊社ブースにお越しいただきました方々本当にありがとうございました！🙇 &lt;a href=&quot;https://t.co/eiAEmaHs6p&quot;&gt;pic.twitter.com/eiAEmaHs6p&lt;/a&gt;&lt;/p&gt;— 株式会社eiicon 開発部 (@eiicon_dev) &lt;a href=&quot;https://x.com/eiicon_dev/status/1934188461940158531?ref_src=twsrc%5Etfw&quot;&gt;June 15, 2025&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.x.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;/div&gt;&lt;div class=&quot;enclosed-tweet&quot; align=&quot;center&quot;&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;
&lt;p lang=&quot;ja&quot; dir=&quot;ltr&quot;&gt;世界の40人に1人がOCamlで仕事したいと思っている、これが民意です&lt;/p&gt;— びしょ〜じょ (@Nymphium) &lt;a href=&quot;https://x.com/Nymphium/status/1934500447915745508?ref_src=twsrc%5Etfw&quot;&gt;June 16, 2025&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.x.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;/div&gt;&lt;p&gt;シールを貼っていただいた言語について自分がたまによくわかんねえ話をするという謎システムですが､盛り上がってよかったです｡感謝&lt;/p&gt;&lt;h1 id=&quot;%E6%84%9F%E6%83%B3&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E6%84%9F%E6%83%B3&quot;&gt;感想&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;まず自分の発表以外の部分｡
最初に言いたいのは…コーヒーがうまかった! ホットとアイスがあって大変うれしかったです｡ありがとうございました｡&lt;/p&gt;&lt;p&gt;Rustにモナドを入れたい話&lt;sup id=&quot;fnref1&quot; title=&quot;Rust世界の二つのモナド──Rust でも do 式をしてプログラムを直感的に記述する件について by konn &quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;はなかなかおもしろく啓発的だった｡
MonadはRustのようなリソースセンシティブな型の上では､継続を使える回数でData Functor(anytime)とControl Functor(up to/ exact once)の2つに分かれる(そしてData Functor ⊃ Affine-Control ones ⊃ Linear-Control ones)(と非線形な富豪モナド)という発表最大のポイントも良かった｡&lt;/p&gt;&lt;p&gt;んですが､ &lt;em&gt;モナドは&lt;code&gt;do&lt;/code&gt;を記述するためのデータ構造&lt;/em&gt; という､おおよそ普段とは逆方向の見方が興味深い｡
&lt;code&gt;do&lt;/code&gt; expressionの初出っぽい&lt;a href=&quot;https://github.com/typeclasses/haskell-report-archive/blob/master/1996-05-haskell-1.3/haskell-report.pdf&quot;&gt;Haskell 1.3 report&lt;/a&gt;では､&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;A do expression provides a more readable syntax for monadic programming.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;とあり､へぇ〜proceduralではないのだな､となるが､proceduralがreadableなことをimplyしてるのかなぁ〜とは思う｡
セミコロンによるsequenceはCなどの手続き的記述を流石に意識してないわけがないだろう｡
確かに副作用が起こる部分が1行ずつに分かれると､プログラムを追うのが大変ラクになる｡
コントロールを直列にする､CPSよりANF､ﾑﾆｬﾑﾆｬ…&lt;/p&gt;&lt;p&gt;非同期のやつ&lt;sup id=&quot;fnref2&quot; title=&quot;ラムダ計算と抽象機械と非同期ランタイム by Kory &quot;&gt;&lt;a href=&quot;#fn2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;は､確かに非同期ランタイムを言語の上でやる場合Freeとインタプリタになって､計算木とCEKだ〜になった｡
CEK tripleを非同期キューで回すことで人々が思うような非同期ランタイムになれるとか､big-step semanticsだと継続が取り出せないんで&lt;sup id=&quot;fnref3&quot; title=&quot;制御演算子を持つ言語を､CPSを使わずに実装すると感覚が得られる: https://github.com/Nymphium/lambdaeff/blob/master/text/main.pdf &quot;&gt;&lt;a href=&quot;#fn3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;非同期ランタイムとしては採用できず､プログラムをナイーブに読むときってbig-step semanticsなのかもなぁ……など｡&lt;/p&gt;&lt;p&gt;Scalaのcats-effectの例は､JVMのJITが頑張るんでナイーブなインタプリタでもOKとのことでしたが､ユーザレベルのランタイムでちゃんとやるってむずいよなぁ〜計算木を最適化するのかインタプリタをCPSで書いて言語自体の処理系がいい感じに最適化してくれるのを祈るかガチgotoで手動dispatchか…楽しいですね｡&lt;/p&gt;&lt;h1 id=&quot;%E8%A3%9C%E8%B6%B3%E3%81%AA%E3%81%A9&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E8%A3%9C%E8%B6%B3%E3%81%AA%E3%81%A9&quot;&gt;補足など&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;完走した感想ですが､もう二度とBeamerでスライドは作りません……&lt;sup id=&quot;fnref4&quot; title=&quot;前回もそう誓ったはずだが…｡ &quot;&gt;&lt;a href=&quot;#fn4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;｡
あと奇しくも知り合いの方が直近で継続の話をしており､タイトルのテイストもなんとなく似ててウケ&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://www.wantedly.com/companies/wantedly/post_articles/890437?utm_source=t.co&amp;amp;utm_medium=share&amp;amp;lang=ja&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://www.wantedly.com/post_articles/890437/ogp_image&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://www.wantedly.com/companies/wantedly/post_articles/890437?utm_source=t.co&amp;amp;utm_medium=share&amp;amp;lang=ja&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;RubyKaigi 2025 で継続の話をしてきました | Wantedly Engineer Blog&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;　ウォンテッドリーのバックエンドエンジニアの水野雅之です。4月16日から18日まで開催された RubyKaigi 2025 において、Ruby にネイティブ実装されている継続オペレータの解説とよ...&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;call/ccよりmodularなshift/resetや! という自分もすこし触れたものをRubyで掘り下げた内容｡
人は一般に､継続で何か話そうとすると､&lt;code&gt;/*Compiling with(out)? Continuations*/&lt;/code&gt;というタイトルを先に考えたくなってしまい､そこから変形するので似てしまうわけですね｡&lt;/p&gt;&lt;p&gt;内容はまぁ〜先述のとおりカツカツだったのでゴチャついてるんですが､functionalとproceduralの比較とエフェクトになんで継続が絡むのかが整理できてよかったかなと｡
前者の対応関係は思ったより評判がよく､継続への理解がしやすいのとCPS-SSAはそんなにメジャーな話じゃないからかな｡
SSAのphi関数は､Join Point&lt;sup id=&quot;fnref5&quot; title=&quot;多分AspectJのJの部分｡ 思っているのはこちらの方: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/11/join-points-pldi17.pdf &quot;&gt;&lt;a href=&quot;#fn5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;とかK-Normal Form&lt;sup id=&quot;fnref6&quot; title=&quot;https://esumii.github.io/min-caml/tutorial-mincaml-9.eng.htm &quot;&gt;&lt;a href=&quot;#fn6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;に当たるが､素のCPSはcontinuationのコピーになる｡ちょっと重いですね｡
話し足りなかった部分でいくと､ANFとかdouble-barreled CPSとかSelective CPSなどといった様々な中間表現…｡&lt;/p&gt;&lt;p&gt;後者については､&lt;a href=&quot;https://nymphium.github.io/2019/07/21/effect_cont.html&quot;&gt;昔ダラダラ書いた内容&lt;/a&gt;をシャキッと話せたんで個人的にかなりスッキリしました｡
悔しいのは､スライド制作でChatGPTと相談していたときにこういった整理をチャGがしてきたこと｡
俺はもうAIに勝てないんや…いや俺のブログ学習してんだろ? 学習禁止〜!!&lt;/p&gt;&lt;p&gt;それはさておき､この発表で継続に興味を持った方とかもちらほら居て､やってよかったなぁ〜…｡&lt;/p&gt;&lt;h2 id=&quot;Q+%E3%81%AA%E3%81%A9&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#Q+%E3%81%AA%E3%81%A9&quot;&gt;Q など&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;バカタレなんで､発表30分前に資料作り終えたんで､発表練習ができず質問時間分も食ってしまった｡
申し訳ございません｡
懇親会などで質問等してくださった方々がおり､大変うれしいですマジで｡&lt;/p&gt;&lt;h3 id=&quot;OCaml%E3%81%AE%E4%BA%BA%E3%82%89%E3%81%8Cshift%2Freset%E3%82%92%E8%AA%9E%E3%82%8B%E3%81%AE%E3%81%AF%E3%81%AA%E3%81%9C&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#OCaml%E3%81%AE%E4%BA%BA%E3%82%89%E3%81%8Cshift%2Freset%E3%82%92%E8%AA%9E%E3%82%8B%E3%81%AE%E3%81%AF%E3%81%AA%E3%81%9C&quot;&gt;OCamlの人らがshift/resetを語るのはなぜ&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;OCamlで限定継続といえば&lt;a href=&quot;https://okmij.org/ftp/continuations/implementations.html&quot;&gt;delimcc&lt;/a&gt;と浅井先生の&lt;a href=&quot;http://pllab.is.ocha.ac.jp/%7Easai/cw2011tutorial/main-j.pdf&quot;&gt;shift/resetプログラミング入門&lt;/a&gt;&lt;sup id=&quot;fnref7&quot; title=&quot;正しくはOCamlではなくてOchaCamlというvariant｡Answer-Type Modificationも導入されており型を含めた限定継続の雰囲気を掴むのに大変よい｡ &quot;&gt;&lt;a href=&quot;#fn7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;なんですが､いずれもshift/resetを題材にしているため｡
Scala2.12に入っていた限定継続もshift/resetじゃなかったか?&lt;/p&gt;&lt;p&gt;スライド中でいっぱいでてきたdelimited controlsたちですが､一番強いのがcontrol0/prompt0で､GHCはさらにプロンプトつきのものを採用している&lt;sup id=&quot;fnref8&quot; title=&quot;https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0313-delimited-continuation-primops.rst &quot;&gt;&lt;a href=&quot;#fn8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;｡
0系のが表現力高いというのは､(中略)よりプリミティブな操作のほうが強いということですね&lt;sup id=&quot;fnref9&quot; title=&quot;継続の中で再度限定継続を取り出すとき､delimiterの指定が自動で入るのがshift/reset等､入らないのがshift0/reset0など0系｡rehandleの自由度が高い(≒表現力が高い)のが後者ということ｡ &quot;&gt;&lt;a href=&quot;#fn9&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;｡&lt;/p&gt;&lt;h3 id=&quot;%E5%A6%84%E6%83%B3+--+parallel+effect+handlers&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E5%A6%84%E6%83%B3+--+parallel+effect+handlers&quot;&gt;妄想 -- parallel effect handlers&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;このあたりの話をしていて&lt;/p&gt;&lt;div class=&quot;github-widget&quot; data-repo=&quot;nymphium/eff.go&quot;&gt;&lt;/div&gt;&lt;p&gt;Goにコルーチンを作ってone-shot algebraic effect handlersといういつものテクをやろうとしたんですが&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://nymphium.github.io/2023/11/27/go-algebraic-effects.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://nymphium.github.io/pictures/github_icon.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://nymphium.github.io/2023/11/27/go-algebraic-effects.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;From Goroutines to Coroutines: goroutines+channelsから考えるコルーチンの分類 - lilyum ensemble&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;こんにちは､びしょ～じょです｡だいぶ前にコルーチンの分類について記事を書きました[1]｡今回は､この分類を実装サイドから考えていこうという企画です｡実装にはGoのgoroutinesとchann...&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;コルーチンの管理にgoroutinesの参照をグローバルなstackで持つということをやっていて､並列にするとぶっ壊れるわけですな｡
事情は全然ちゃうんだけど､並列処理が標準で使えるようになったOCamlのalgebraic effect handlersでも､エフェクトの捕捉はスレッドをまたげないという制約がある｡
C FFIのコールスタックをまたげないという部分とも絡んでいるが､まあ､無理っちゅうわけですな｡
パラフレーズしておいてどれくらい関連あるか謎なんだけど､algebraic effect handlersは並列に少し弱いらしい｡&lt;/p&gt;&lt;p&gt;ランタイムの継続の表現､つまりコールスタックと変数ストアをポータブルな形にするとか､Cの呼び出し部分とのcompatibilityを保つとか､そのあたりをケアした話が出るんじゃないかなぁという妄想を語った｡
先に実装の話が､それこそOCamlのグループから出て来ると思うが､物好きな理論系の人が並列計算+代数的効果のモデルを提案するかもしれない｡&lt;/p&gt;&lt;h3 id=&quot;%22%E7%B6%99%E7%B6%9A%22%E3%81%A8%E3%81%84%E3%81%86%E9%82%A6%E8%A8%B3%E2%80%A6%E2%80%A6&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%22%E7%B6%99%E7%B6%9A%22%E3%81%A8%E3%81%84%E3%81%86%E9%82%A6%E8%A8%B3%E2%80%A6%E2%80%A6&quot;&gt;&quot;継続&quot;という邦訳……&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&quot;Continuations&quot;なんだからまあ&quot;継続&quot;ではあるが､じゃあ先に&quot;継続&quot;がでてきたらどう思いますか?
確かに……残りの計算というモノっぽい概念に対して&quot;継続&quot;って､あまり日本語話者の感覚ではない気がする｡
という話をしたら&quot;残りの計算&quot;もなんだか分からんと｡
&quot;計算&quot;もなんやねん! と｡&lt;/p&gt;&lt;p&gt;継続はstaticなのに&quot;継続&quot;といういかにもdynamicな語がワカラン! と言われたんですが､これはそもそも継続がdynamicなんですな｡
CPSにするとまあなんとなく感覚が掴めて､ほらCPS変換で得られたmetacontinuationは実行時に到達するんだしdynamicやないですか?
と説明したんだけど､だからって継続……ウーン……あなたはタイムスリップできたらもっとプロパーな名前付けられそうですか?&lt;/p&gt;&lt;h3 id=&quot;Haskell%E3%81%AA%E3%81%AB%E3%81%8C%E7%B4%94%E7%B2%8B%E3%82%84%E3%81%AD%E3%82%93%E4%BD%95%E3%81%8Cdo%E3%81%A0%E3%83%A2%E3%83%8A%E3%83%89%E3%81%A0&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#Haskell%E3%81%AA%E3%81%AB%E3%81%8C%E7%B4%94%E7%B2%8B%E3%82%84%E3%81%AD%E3%82%93%E4%BD%95%E3%81%8Cdo%E3%81%A0%E3%83%A2%E3%83%8A%E3%83%89%E3%81%A0&quot;&gt;Haskellなにが純粋やねん何がdoだモナドだ&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;igrepさんと懇親会でお話して､彼の発表にもある↑について
&lt;a href=&quot;https://the.igreque.info/slides/2025-06-15-fp-matsuri#(22)&quot;&gt;https://the.igreque.info/slides/2025-06-15-fp-matsuri#(22)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;私も昔は確かに､IOは実際に発火してんだから純粋じゃないやんけHaskellerは詐欺師集団か!! と憤りを覚えたこともある｡
まあ今なら､純粋は &quot;(Monadでエフェクトを隠蔽しているのであたかも)純粋(かのようにプログラムを記述し､&lt;code&gt;main&lt;/code&gt;に&lt;code&gt;IO a&lt;/code&gt;を接着させないと発火しませんよ)&quot;の略であることは分かる｡
ただ､この&quot;純粋&quot;が略語であることを初心者は分からないんで､確かに純粋関数型言語って何言ってんだコイツにはなる｡
この辺もうすこし議論があるらしいんですが､議論のすえHaskellが&quot;純粋&quot;の看板を下ろしてもランタイムとIOのシステムは変わらないと思うんで､別にこの辺のレトリックにこだわらなくていいです(という話を↑ですこししてくれています)｡&lt;/p&gt;&lt;p&gt;IOプログラミングの本質は順序があってchainするという部分の話を共感してもらえ､手続き的に書く(&lt;code&gt;do&lt;/code&gt;)にはmonadという構造が必要になる､というkonnさんの話にも戻っていって､エッセンシャルな部分なんやなぁということが再確認できた｡&lt;/p&gt;&lt;h3 id=&quot;fcontrol%2Frun%E3%81%A8SCIENCE+TOKYO&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#fcontrol%2Frun%E3%81%A8SCIENCE+TOKYO&quot;&gt;fcontrol/runとSCIENCE TOKYO&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;SCIENCE TOKYOでは某お茶女の研究室を出た方が継続を布教しまくってるらしい｡
今年のPPLではポスター発表にて､私も熱烈推奨しているfcontrol/runが理解しやすく学生ウケがよいという話を聞いた｡
しかし懇親会でshift/resetのみならずfcontrol/runも講義でもはや利用されてないと言われ椅子から転げ落ち横転して号泣して顔がなくなった｡
しかしよく聞くと､全部algebraic effect handlersに統一されるとのことで､逆にどうなってんねん､と真顔になった｡
SCIENCE TOKYOでとんでもないことが起きてますよ｡&lt;/p&gt;&lt;h3 id=&quot;WASM%E3%81%A8effect+handler&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#WASM%E3%81%A8effect+handler&quot;&gt;WASMとeffect handler&lt;/a&gt;&lt;/h3&gt;&lt;div class=&quot;enclosed-tweet&quot; align=&quot;center&quot;&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;
&lt;p lang=&quot;ja&quot; dir=&quot;ltr&quot;&gt;wasm effect handler もう動いてるんだっけ&lt;a href=&quot;https://t.co/z485QM5zrC&quot;&gt;https://t.co/z485QM5zrC&lt;/a&gt;&lt;br&gt;&lt;br&gt; &lt;a href=&quot;https://x.com/hashtag/fp_matsuri_a?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#fp_matsuri_a&lt;/a&gt;&lt;/p&gt;— mizchi (@mizchi) &lt;a href=&quot;https://x.com/mizchi/status/1933808299285389329?ref_src=twsrc%5Etfw&quot;&gt;June 14, 2025&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.x.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;/div&gt;&lt;p&gt;なぁWasmFX､息してるか…? してる…&lt;/p&gt;&lt;div class=&quot;github-widget&quot; data-repo=&quot;wasmfx/specfx&quot;&gt;&lt;/div&gt;&lt;p&gt;発表で触れたOCamlのWASMバックエンドはselective CPSまたはJSPIでPromiseに変換される&lt;sup id=&quot;fnref10&quot; title=&quot;https://github.com/ocsigen/js_of_ocaml/blob/master/manual/effects.wiki &quot;&gt;&lt;a href=&quot;#fn10&quot;&gt;10&lt;/a&gt;&lt;/sup&gt; &lt;sup id=&quot;fnref11&quot; title=&quot;https://v8.dev/blog/jspi &quot;&gt;&lt;a href=&quot;#fn11&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;｡
特にJSPIでOKなのは継続がone-shotなところが出たわね｡&lt;/p&gt;&lt;h3 id=&quot;%E3%81%9D%E3%81%AE%E4%BB%96&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E3%81%9D%E3%81%AE%E4%BB%96&quot;&gt;その他&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;2日目に発表していたYoutuberの大堀さん…いや､あの大堀先生が､奇跡的なかみ合わせで本日継続に関する動画を投稿してました｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=0ViMkBxYsnk&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=0ViMkBxYsnk&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;継続に興味持った方も持ってない方も絶対これ見たほうが良いです｡
2日目のSML#の話を､大堀先生と上野先生の2連続で聞けたのも大変すばらしかった｡&lt;/p&gt;&lt;h1 id=&quot;%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;おわりに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;わりと満足｡&lt;/p&gt;&lt;p&gt;このブログの読者ですという人々がたまに弊社ブースなどでお声がけしてくださったりして大変うれしかったです｡
令和の日本において信仰の自由は保証されているので､弊ブログのファンというのはもっと声を大にしていただいて大丈夫です｡多分迫害されません｡&lt;/p&gt;&lt;div class=&quot;enclosed-tweet&quot; align=&quot;center&quot;&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;
&lt;p lang=&quot;ja&quot; dir=&quot;ltr&quot;&gt;うおｗ &lt;a href=&quot;https://t.co/O32xGI86mh&quot;&gt;pic.twitter.com/O32xGI86mh&lt;/a&gt;&lt;/p&gt;— びしょ〜じょ (@Nymphium) &lt;a href=&quot;https://x.com/Nymphium/status/1933706679985811725?ref_src=twsrc%5Etfw&quot;&gt;June 14, 2025&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.x.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;/div&gt;&lt;p&gt;元同僚の方に｢江の島のチューリングと呼ばれている｣まで詠唱されてウケました｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://nymphium.github.io/2023/02/20/migrate_enoshima.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://nymphium.github.io/pictures/github_icon.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://nymphium.github.io/2023/02/20/migrate_enoshima.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;江ノ島のチューリングと呼ばれて(ない)1年 - lilyum ensemble&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;はじめにこんにちは､びしょ～じょです｡実は1年前に守谷から江ノ島の前に引っ越してまして｡せっかくなんで一筆したためる｡新居情報あざす pic.twitter.com/kthNIMNKZe— びし...&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;

&lt;li id=&quot;fn1&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://fortee.jp/2025fp-matsuri/proposal/a8cd6d02-37c5-4009-90a4-9495c3189420&quot;&gt;Rust世界の二つのモナド──Rust でも do 式をしてプログラムを直感的に記述する件について by konn&lt;/a&gt; &lt;a href=&quot;#fnref1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn2&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://fortee.jp/2025fp-matsuri/proposal/3bdbadb9-7d77-4de0-aa37-5a7a38c577c3&quot;&gt;ラムダ計算と抽象機械と非同期ランタイム by Kory&lt;/a&gt; &lt;a href=&quot;#fnref2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn3&quot;&gt;
&lt;p&gt;制御演算子を持つ言語を､CPSを使わずに実装すると感覚が得られる: &lt;a href=&quot;https://github.com/Nymphium/lambdaeff/blob/master/text/main.pdf&quot;&gt;https://github.com/Nymphium/lambdaeff/blob/master/text/main.pdf&lt;/a&gt; &lt;a href=&quot;#fnref3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn4&quot;&gt;
&lt;p&gt;前回もそう誓ったはずだが…｡ &lt;a href=&quot;#fnref4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn5&quot;&gt;
&lt;p&gt;多分AspectJのJの部分｡ 思っているのはこちらの方: &lt;a href=&quot;https://www.microsoft.com/en-us/research/wp-content/uploads/2016/11/join-points-pldi17.pdf&quot;&gt;https://www.microsoft.com/en-us/research/wp-content/uploads/2016/11/join-points-pldi17.pdf&lt;/a&gt; &lt;a href=&quot;#fnref5&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn6&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://esumii.github.io/min-caml/tutorial-mincaml-9.eng.htm&quot;&gt;https://esumii.github.io/min-caml/tutorial-mincaml-9.eng.htm&lt;/a&gt; &lt;a href=&quot;#fnref6&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn7&quot;&gt;
&lt;p&gt;正しくはOCamlではなくてOchaCamlというvariant｡Answer-Type Modificationも導入されており型を含めた限定継続の雰囲気を掴むのに大変よい｡ &lt;a href=&quot;#fnref7&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn8&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0313-delimited-continuation-primops.rst&quot;&gt;https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0313-delimited-continuation-primops.rst&lt;/a&gt; &lt;a href=&quot;#fnref8&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn9&quot;&gt;
&lt;p&gt;継続の中で再度限定継続を取り出すとき､delimiterの指定が自動で入るのがshift/reset等､入らないのがshift0/reset0など0系｡rehandleの自由度が高い(≒表現力が高い)のが後者ということ｡ &lt;a href=&quot;#fnref9&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn10&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ocsigen/js_of_ocaml/blob/master/manual/effects.wiki&quot;&gt;https://github.com/ocsigen/js_of_ocaml/blob/master/manual/effects.wiki&lt;/a&gt; &lt;a href=&quot;#fnref10&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id=&quot;fn11&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://v8.dev/blog/jspi&quot;&gt;https://v8.dev/blog/jspi&lt;/a&gt; &lt;a href=&quot;#fnref11&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;/div&gt;</description>
        <pubDate>Tue, 17 Jun 2025 00:00:00 +0000</pubDate>
        <link>https://nymphium.github.io/2025/06/17/fpmatsuri-ty.html</link>
        <guid isPermaLink="true">https://nymphium.github.io/2025/06/17/fpmatsuri-ty.html</guid>
        
        <category>関数型まつり</category>
        
        <category>Continuations</category>
        
        <category>雑感</category>
        
        
      </item>
    
      <item>
        <title>キーボードアルティメイタム 第2話 Corne V4 Chocolate</title>
        <enclosure type="image/png" length="0" url="https://nymphium.github.io/pictures/github_icon.png"></enclosure>
        <description>&lt;p&gt;こんにちは､びしょ〜じょです｡&lt;/p&gt;&lt;p&gt;最近『教皇選挙』を観ました｡
お前は観たか? 観たほうがいいぞ｡&lt;/p&gt;&lt;p&gt;内容○､画○､音響○なんで､キリスト教世界観分かるパーソンだったら更に面白く観られる気がします｡&lt;/p&gt;&lt;h1 id=&quot;1.+%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB+%E6%9D%90%E6%96%99%E8%AA%BF%E9%81%94%E9%83%A8%E9%96%80&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#1.+%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB+%E6%9D%90%E6%96%99%E8%AA%BF%E9%81%94%E9%83%A8%E9%96%80&quot;&gt;1. はじめに 材料調達部門&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;頭がおかしくなってキーボードを買った｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://shop.yushakobo.jp/products/8962&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://shop.yushakobo.jp/cdn/shop/files/IMG_20240316_192605_600x600_crop_center.jpg?v=1710585011&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://shop.yushakobo.jp/products/8962&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Corne V4 Chocolate&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;左右分割キーボードに関する注意事項左右のキーボードをTRRSケーブルで接続したまま、両方のキーボードを同時にPCとUSB接続しないでください。PCとキーボードを接続中に、左右間を接続するTRRSケーブルを挿抜しないでください。キーボードおよびPCに深刻なダメージが発生する可能性があります。EMI（electromagnetic interference）による動作不良に関する注意事項現在販売している基板において、EMI（電磁干渉）による不具合の報告が寄せられています。 これはスマートフォン等の機器が近くにある場合によく発生し、環境により、左右の片方もしくは両方のキーボードが動作不良に陥ります。このような症状が発生した場合、一度USB接続を解除し、機器をキーボードから30cm以上離してから再接続してください。詳細についてはこちら。Corne V4 Chocolateとはfoostan氏によりデザインされた分割キーボードのベストセラー、Corneシリーズの最新作横6 x 縦3キーのcolumn staggered配列(列方向にずらした配列) + 親指3キーの左右分離型キーボードです。キー数は左右合わせて最大46個のみで非常にコンパクトな設計となっています。40%分離型キーボードの代表格であるLet&apos;s Splitよりも小型であり、Irisから数字列を外したような配置になっています。V4の特徴はんだ付け不要ファームウェア書き込み済み専用ケースの付属RemapによるWebブラウザからの簡単なキーマップのカスタムホットスワップ可能フルキーバックライト対応はんだ付けが不要かつファームウェアも書き込み済みのため簡単に組み立てができ、すぐに使用できます。さらに専用のケースが付属します。高級感のある見た目や打鍵音にもこだわったキットです。V3からの変更点はこちらをご参照くださいデフォルトキーマップは以下をご覧ください（中央4キーは未割り当てです）内容物実装済み基板（Ver.4.1）　…　左右各1枚ケース　…　左右セットマウントプレート　…　2枚スペーサー M2 5mm　…　8本ネジ　M2 4.5mm　…　16本クッションゴム　…　8個別途ご用意が必要なものキースイッチ（Kailh Choc V1もしくはV2対応の物）×46個キーキャップ（Kailh Choc V1もしくはV2対応の物）×46個USB Type-Cケーブル … 1本TRRSメタルケーブル 0.8m … 1本※ CherryMX互換スイッチには対応しておりません組み立て方法ビルドガイドはこちらをご参照ください。https://github.com/foostan/crkbd/blob/v4.0/docs/corne-chocolate/v4/buildguide_jp.md関連商品キーボードアクリルプレートCorne V4 Chocolateに付属しているFR4製のマウントプレート（スイッチプレート）を交換し、アクリルに変更できるサービスです。下記が該当のプレートです。「Corne V4 Chocolate フルバージョン - 2mm」「Corne V4 Chocolate レガシーバージョン - 2mm」キーボードフォームカットサービスCorne V4 Chocolateに取り付けることができるPoron製のフォームをカットするサービスです。下記が該当のフォームです。「Corne V4 共通（ボトム） - 2mm」「Corne V4 共通（ボトム） - 3mm」キーボードカスタムプレート プリントサービスCorne V4 Chocolateのスイッチプレート（アクリル製）にUVプリントを行うことで、カスタムできるサービスです。下記が該当のプレートです。「Corne V4 Chocolate フルバージョン - 2mm」「Corne V4 Chocolate レガシーバージョン - 2mm」免責事項写真は作成見本であり商品内容と同一ではありません。また仕様は予告なく変更することがあります。&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;ファームウェアはqmk&lt;/li&gt;
&lt;li&gt;いわゆる40%分割型

&lt;ul&gt;
&lt;li&gt;数字キーが無い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ビカビカ光る&lt;/li&gt;
&lt;li&gt;ホットスワップ

&lt;ul&gt;
&lt;li&gt;ソケットはすでに着いてるのでキースイッチ(別売)を刺すだけ&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;というのが特徴｡
数字キーいらねえんじゃねえのとなって､こうなった｡
ErgoDox EZからの乗り換えになる｡&lt;/p&gt;&lt;center&gt;
&lt;label id=&quot;size&quot;&gt;&lt;/label&gt;
&lt;img src=&quot;/pictures//2025/05/02/ultimate-keyboarding/comparing-size.jpg&quot; alt=&quot;サイズ比較&quot; width=&quot;80%&quot;&gt;
図&lt;a href=&quot;#size&quot;&gt;1.1&lt;/a&gt;. サイズ比較｡手前がCorne､上の黒いのがErgoDox EZで白いのがMoonlander
&lt;/center&gt;&lt;p&gt;キースイッチはKailhのChoc v2 Deep Sea Silent Isletという結構新しいやつを買った｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://keeb-on.com/products/kailh-choc-v2-deep-sea-silent&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;http://keeb-on.com/cdn/shop/files/P8070011.jpg?v=1723180548&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://keeb-on.com/products/kailh-choc-v2-deep-sea-silent&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kailh Choc v2 Deep Sea Silent Islet Switch&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;このスイッチは近年人気が出てきているChoc v2スイッチの静音版です。喫茶店などの静かな環境で打鍵する際に特にオススメです。逆に打鍵感を楽しめる場合は、Kailh Choc v2 White Rain Switchの方が軸ブレが少なくスムーズに動作する印象があります。またフォースカーブの右側を見ると分かりますが、このスイッチは底打ち時の衝撃を柔らかくする効果がありますので、ErgoArrowsProのような剛性が高いキーボードに特にオススメです。&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;HHKBみたいな､少しザラっとしてるけど滑らかな静音リニアで気持ちがいい｡
流通が少なそうなのがネック｡&lt;/p&gt;&lt;p&gt;親指で押すキーは軽くしたいのでChoc v1のピンク軸にした｡
v1とv2はソケット互換があるのでどちらも使える｡一方キャップに互換はない｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://shop.yushakobo.jp/products/pg1350?variant=44079245754599&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://shop.yushakobo.jp/cdn/shop/products/P1281512_600x600_crop_center.jpg?v=1643357648&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://shop.yushakobo.jp/products/pg1350?variant=44079245754599&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Kailhロープロファイルスイッチ&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;※キースイッチのみの商品です。キーボード等は含まれません。※キースイッチの品質に関する免責事項を必ずご覧になってからお買い求めください。ロープロファイルスイッチ（Choc V1）です。赤軸：スムーズなリニア軸茶軸：クリック感のあるタクタイル軸白軸：カチカチ感のあるクリッキー軸Red Pro：軽くてスムーズなリニア軸Pink：さらに軽くてスムーズなリニア軸赤軸スイッチ互換性：Choc V1スイッチタイプ：リニア押下圧：約45g±10gf動作圧：約50g±10gfストローク：3.0mm±0.5mm接点：1.5mm±0.5mmPCBマウント（5ピン）型番：CPG135001D01メーカープロダクトページデータシート赤軸茶軸スイッチ互換性：Choc V1スイッチタイプ：タクタイル押下圧：約45g±15gf動作圧：約60g±10gfストローク：3.0mm±0.5mm接点：1.5mm±0.5mmPCBマウント（5ピン）型番：CPG135001D02メーカープロダクトページデータシート茶軸白軸スイッチ互換性：Choc V1スイッチタイプ：クリッキー押下圧：約50g±10gf動作圧：約60g±10gfストローク：3.0mm±0.5mm接点：1.5mm±0.5mmPCBマウント（5ピン）型番：CPG135001D03メーカープロダクトページデータシート白軸Red Proスイッチ互換性：Choc V1スイッチタイプ：リニア動作圧：約35gfストローク：3.0mm±0.5mm接点：1.5mm±0.5mmPCBマウント（5ピン）Pinkスイッチ互換性：Choc V1スイッチタイプ：リニア動作圧：約20gfストローク：3.0mm±0.5mm接点：1.5mm±0.5mmPCBマウント（5ピン）データシート　　　　　Pink&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;めちゃ軽く手への負担は少ないが､Isletが静音すぎて相対的にカチャカチャ音が気になるのが玉に瑕｡&lt;/p&gt;&lt;h1 id=&quot;2.+qmk_firmware+%E5%B0%8F%E3%83%86%E3%82%AF%E9%9B%86&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2.+qmk_firmware+%E5%B0%8F%E3%83%86%E3%82%AF%E9%9B%86&quot;&gt;2. qmk_firmware 小テク集&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;xmodmapでキーマップを変更していた10年以上前から入力の歴史は続いており(中略)(攻略)｡
&lt;a href=&quot;https://github.com/Nymphium/qmk_firmware/blob/811c21b4822b8fddf76aa04578e84e259b8d9b1a/keyboards/ergodox_ez/keymaps/nymphium/keymap.c&quot;&gt;ErgoDox EZのキーマップ&lt;/a&gt;をベースにした｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://github.com/Nymphium/qmk_firmware/blob/bdee63cabddf0aefa192d44ff0f894eaf7e07f8f/keyboards/crkbd/keymaps/nymphium/keymap.c&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://opengraph.githubassets.com/1f4d93402dca88fdbd9a9e3f11766e03be4af1c806d933f857dff8fa3b128fa5/Nymphium/qmk_firmware&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://github.com/Nymphium/qmk_firmware/blob/bdee63cabddf0aefa192d44ff0f894eaf7e07f8f/keyboards/crkbd/keymaps/nymphium/keymap.c&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;qmk_firmware/keyboards/crkbd/keymaps/nymphium/keymap.c at bdee63cabddf0aefa192d44ff0f894eaf7e07f8f · Nymphium/qmk_firmware&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;keyboard controller firmware for Atmel AVR and ARM USB families - Nymphium/qmk_firmware&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;キーボードがだいぶ小さくなったんで､マウス操作レイヤーと数字操作レイヤーを追加する｡
shift+数字も変更したいので､それ用のレイヤーも追加する｡&lt;/p&gt;&lt;h2 id=&quot;2-1.+tri+layer&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2-1.+tri+layer&quot;&gt;2-1. tri layer&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;LOWER&lt;/code&gt;レイヤーでの入力にshift modifierを適用したい場合､ナイーブにシフトキーだけ押すとうまくいかない｡
うまくいかないんで､ &lt;code&gt;layer_state_set_user&lt;/code&gt;関数内で&lt;code&gt;update_tri_layer_state&lt;/code&gt;を使って複数レイヤーをまたぐ場合のルールを登録する｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://docs.qmk.fm/features/tri_layer#tri-layers&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://docs.qmk.fm/features/tri_layer#tri-layers&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Tri Layers | QMK Firmware&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Documentation for QMK Firmware&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/c/c-original.svg&quot; alt=&quot;c&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;&lt;label id=&quot;layer_state&quot;&gt;&lt;/label&gt;keymap.c&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;n&quot;&gt;layer_state_t&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;layer_state_set_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layer_state_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;update_tri_layer_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_LOWER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_SHIFT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_LSHIFT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;update_tri_layer_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_NUM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_LOWER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_NMODS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;center&gt;
図&lt;a href=&quot;#layer_state&quot;&gt;2.1&lt;/a&gt;. `update_tri_layer_state` の使い所さん
&lt;/center&gt;&lt;p&gt;Shiftキーを押したときに&lt;code&gt;_SHIFT&lt;/code&gt;レイヤーに移行すればよい｡
このとき&lt;code&gt;_SHIFT&lt;/code&gt;は何も登録してないレイヤーでよい｡&lt;/p&gt;&lt;p&gt;これで､&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;_LOWER&lt;/code&gt;かつ&lt;code&gt;_SHIFT&lt;/code&gt;のとき､&lt;code&gt;_LSHIFT&lt;/code&gt;レイヤーに移行&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_NUM&lt;/code&gt;かつ&lt;code&gt;_LOWER&lt;/code&gt;のとき､&lt;code&gt;_NMODS&lt;/code&gt;レイヤーに移行&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;する｡
ちなむとcomboもうまくいかない｡switching layer系の組み合わせもうまくいかない｡
皆さんも諦めるか､smarterな解法があったら教えて下さい｡&lt;/p&gt;&lt;h2 id=&quot;2-2.+key+override&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2-2.+key+override&quot;&gt;2-2. key override&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;QMKを触っていると人々はレイヤーがサァ! とか色気づくんだけど､modifier key+key→別のキーに変換というナイーブな機能がある｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://docs.qmk.fm/features/key_overrides&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://docs.qmk.fm/features/key_overrides&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Key Overrides | QMK Firmware&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Documentation for QMK Firmware&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/c/c-original.svg&quot; alt=&quot;c&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;&lt;label id=&quot;key_overrid&quot;&gt;&lt;/label&gt; keymap.c&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_override_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key_overrides&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ko_make_basic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MOD_MASK_SHIFT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;KC_0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;JP_QUES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;center&gt;
図&lt;a href=&quot;#key_overrid&quot;&gt;2.2&lt;/a&gt;. key overrideでShift+0→`?`を出す
&lt;/center&gt;&lt;p&gt;Shift+0で&lt;code&gt;?&lt;/code&gt;が出てくるようになる｡
ちなみに俺は普通のキーボードでShift+0すると何が入力されるのかもう覚えてない｡&lt;/p&gt;&lt;h2 id=&quot;2-3.+%E3%83%9E%E3%82%A6%E3%82%B9%E4%B8%AD%E3%82%AF%E3%83%AA%E3%83%83%E3%82%AF%2F%E3%83%9B%E3%82%A4%E3%83%BC%E3%83%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2-3.+%E3%83%9E%E3%82%A6%E3%82%B9%E4%B8%AD%E3%82%AF%E3%83%AA%E3%83%83%E3%82%AF%2F%E3%83%9B%E3%82%A4%E3%83%BC%E3%83%AB&quot;&gt;2-3. マウス中クリック/ホイール&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;マウスホイールの中クリックを皆さん使っているか?
ブラウザのリンクを中クリックすると新しいタブで開いたり､タブを中クリックするとcloseしたりする優れモノです｡&lt;/p&gt;&lt;p&gt;qmk_firmwareはマウスエミュレーションができる｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://docs.qmk.fm/features/mouse_keys&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://docs.qmk.fm/features/mouse_keys&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mouse keys | QMK Firmware&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Documentation for QMK Firmware&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;QMKと中クリックは人生のテーマだったんですが､&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/c/c-original.svg&quot; alt=&quot;c&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;&lt;label id=&quot;struggle_middle&quot;&gt;&lt;/label&gt;process_record_user.switch in keymap.c&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MIDDLE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pressed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;register_code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KC_BTN3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;WAIT_PRESSING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;unregister_code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;KC_BTN3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;layer_on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_WHEEL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;layer_off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_WHEEL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;center&gt;
図&lt;a href=&quot;#struggle_middle&quot;&gt;2.3&lt;/a&gt;. 中クリック/ホイールの実装(incorrect)
&lt;/center&gt;&lt;p&gt;プログラム&lt;a href=&quot;#struggle_middle&quot;&gt;2.3&lt;/a&gt;だと先中クリックが入力されるため､ホイール操作だけしたいのに変にリンクを開いたりしてしまい､Webサイトのスクロールできるtable of contentsでスクロールするつもりがうっかり別タブを開いてしまう事故が多々おきた｡&lt;/p&gt;&lt;p&gt;鬼の努力は実はたった1行で解決できる｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/c/c-original.svg&quot; alt=&quot;c&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;&lt;label id=&quot;lt_middle&quot;&gt;&lt;/label&gt;keymap.c&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#define MIDDLE LT(_WHEEL, KC_BTN3)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;center&gt;
図&lt;a href=&quot;#lt_middle&quot;&gt;2.4&lt;/a&gt;. 中クリック/ホイールの実装(correct)
&lt;/center&gt;&lt;p&gt;これをkeymapで呼ぶだけ｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://docs.qmk.fm/feature_layers#switching-and-toggling-layers&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://docs.qmk.fm/feature_layers#switching-and-toggling-layers&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Layers | QMK Firmware&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Documentation for QMK Firmware&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;ドキュメントはちゃんと隅々まで嫁ってことですな…w&lt;/p&gt;&lt;h2 id=&quot;2-4.+%E3%83%AC%E3%82%A4%E3%83%A4%E3%83%BC%E6%95%B0%E5%A2%97%E3%82%84%E3%81%99&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2-4.+%E3%83%AC%E3%82%A4%E3%83%A4%E3%83%BC%E6%95%B0%E5%A2%97%E3%82%84%E3%81%99&quot;&gt;2-4. レイヤー数増やす&lt;/a&gt;&lt;/h2&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/c/c-original.svg&quot; alt=&quot;c&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;&lt;label id=&quot;layer_count&quot;&gt;&lt;/label&gt;config.h&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#undef DYNAMIC_KEYMAP_LAYER_COUNT
#define DYNAMIC_KEYMAP_LAYER_COUNT 9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;center&gt;
図&lt;a href=&quot;#layer_count&quot;&gt;2.5&lt;/a&gt;. レイヤー数を増やす
&lt;/center&gt;&lt;p&gt;はいこれです｡
これを書かずに7以上のレイヤーを定義するとコンパイラが｢&lt;code&gt;DYNAMIC_KEYMAP_LAYER_COUNT&lt;/code&gt; は6や!!｣と怒ってくるので､察せられます｡&lt;/p&gt;&lt;h1 id=&quot;3.+%E3%83%9E%E3%82%A6%E3%82%B9tips&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#3.+%E3%83%9E%E3%82%A6%E3%82%B9tips&quot;&gt;3. マウスtips&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;多分世の中には多くのqmkマウスエミュレーション愛好家がいると思うんですが､私もその一人でしてェ…｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://docs.qmk.fm/features/mouse_keys&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;/pictures/no_image.png&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://docs.qmk.fm/features/mouse_keys&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Mouse keys | QMK Firmware&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Documentation for QMK Firmware&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;一旦こうなっている｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/c/c-original.svg&quot; alt=&quot;c&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;&lt;label id=&quot;config_mouse&quot;&gt;&lt;/label&gt;config.h&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#define MK_KINETIC_SPEED
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#undef MOUSEKEY_DELAY
#define MOUSEKEY_DELAY 0
#undef MOUSEKEY_INITIAL_SPEED
#define MOUSEKEY_INITIAL_SPEED 80
#undef MOUSEKEY_MOVE_DELTA
#define MOUSEKEY_MOVE_DELTA 8
#undef MOUSEKEY_BASE_SPEED
#define MOUSEKEY_BASE_SPEED 2200
&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#undef MOUSEKEY_WHEEL_DELAY
#define MOUSEKEY_WHEEL_DELAY 3
#define MOUSEKEY_WHEEL_INTERVAL 40
#define MOUSEKEY_WHEEL_MAX_SPEED 12
#define MOUSEKEY_WHEEL_TIME_TO_MAX 16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;center&gt;
図&lt;a href=&quot;#config_mouse&quot;&gt;3.1&lt;/a&gt;. マウスのパラメータ〜
&lt;/center&gt;&lt;p&gt;Kineticモードはカーソルの速度がquadratic curveで加速するため､最大速度から逆算すると初動からしばらく小さく動けるので､繊細に動かせるし遠くに動かしたいときも困らない｡
&lt;code&gt;MOVE_DELTA&lt;/code&gt;で加速度合いを変更し､&lt;code&gt;BASE_SPEED&lt;/code&gt; まで (&lt;code&gt;BASE_SPEED - INITIAL_SPEED) / MOVE_DELTA&lt;/code&gt; millisecかけて加速していく｡&lt;/p&gt;&lt;p&gt;結局この辺は好みなんで快適な数値を探してください(爆)&lt;/p&gt;&lt;h1 id=&quot;4.+%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#4.+%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;4. おわりに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;いかがでしたか?&lt;/p&gt;&lt;p&gt;ちなみに第1話はない｡&lt;/p&gt;&lt;h1 id=&quot;5.+%E3%81%8A%E3%81%BE%E3%81%91&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#5.+%E3%81%8A%E3%81%BE%E3%81%91&quot;&gt;5. おまけ&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;ありすぎだろ&lt;/p&gt;&lt;div class=&quot;enclosed-tweet&quot; align=&quot;center&quot;&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;
&lt;p lang=&quot;ja&quot; dir=&quot;ltr&quot;&gt;壊れたキーボード直してたら家にキーボードありすぎることに気付いた &lt;a href=&quot;https://t.co/C5PgB5V2sm&quot;&gt;pic.twitter.com/C5PgB5V2sm&lt;/a&gt;&lt;/p&gt;— びしょ〜じょ (@Nymphium) &lt;a href=&quot;https://x.com/Nymphium/status/1917971194021842950?ref_src=twsrc%5Etfw&quot;&gt;May 1, 2025&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.x.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;/div&gt;&lt;p&gt;TEXシリーズはYodaからぼちぼち買ってるので愛着がある｡
奥にあるLogiのG515もG HBUという専用のソフトウェアでレイヤー機能や様々なカスタマイズができるんで使い勝手がよい｡&lt;/p&gt;&lt;p&gt;なんとなくほしいな〜とかゲームしたいな〜となると､増えてしまうわけですね｡&lt;/p&gt;</description>
        <pubDate>Fri, 02 May 2025 00:00:00 +0000</pubDate>
        <link>https://nymphium.github.io/2025/05/02/ultimate-keyboarding.html</link>
        <guid isPermaLink="true">https://nymphium.github.io/2025/05/02/ultimate-keyboarding.html</guid>
        
        <category>自作キーボード</category>
        
        <category>qmk_firmware</category>
        
        
      </item>
    
      <item>
        <title>DependabotのPRにフックして追いcommitする</title>
        <enclosure type="image/png" length="0" url="https://nymphium.github.io/pictures//2025/03/31/dependabot-hook/thumb.png"></enclosure>
        <description>&lt;p&gt;こんにちは､びしょ〜じょです｡&lt;/p&gt;&lt;p&gt;寒すぎる｡俺達の春を返せよ…｡&lt;/p&gt;&lt;h1 id=&quot;1.+%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#1.+%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB&quot;&gt;1. はじめに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;本ブログはJekyllで運用されており､GitHubでホストされ､Dependabotで依存ライブラリのアップデートを最近自動化した｡&lt;/p&gt;&lt;p&gt;ところで､このシステムでは開発にNixを使っており､&lt;a href=&quot;https://github.com/inscapist/ruby-nix&quot;&gt;ruby-nix&lt;/a&gt;によってRubyの依存ライブラリをNix化している｡
&lt;a href=&quot;https://github.com/Nymphium/nymphium.github.io/blob/75e1119fbc2e3effc73efcc47feb8e87ff477b78/nix/bundix.nix&quot;&gt;bundix&lt;/a&gt;でGemfile.lockからgemset.nixを生成し､ruby-nixでNix化されたgemsのパスが通っているshellが動いており､そこで開発をおこなう｡&lt;/p&gt;&lt;p&gt;でもよぉDependabotのPRではgemset更新してくれないやんけ､ということで↓をやりたい｡&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;DependabotがGemfile{,.lock}更新のPRが出たら&lt;/li&gt;
&lt;li&gt;PRにhookして

&lt;ol&gt;
&lt;li&gt;gemset.nixを更新して&lt;/li&gt;
&lt;li&gt;PR branchにpushする&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;h1 id=&quot;2.+hook+%E3%82%84%E3%82%8A%E3%81%8B%E3%81%9F&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#2.+hook+%E3%82%84%E3%82%8A%E3%81%8B%E3%81%9F&quot;&gt;2. hook やりかた&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;DependabotのPRがどういう挙動をするかを確認する｡
例えばこのPR:
&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://github.com/Nymphium/nymphium.github.io/pull/65&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://opengraph.githubassets.com/d3d88c28648a3c9cc4421313bc48b557abae6bea65b53d3d8283bff984bd572f/Nymphium/nymphium.github.io/pull/65&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://github.com/Nymphium/nymphium.github.io/pull/65&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Bump nokogiri from 1.18.2 to 1.18.3 by dependabot[bot] · Pull Request #65 · Nymphium/nymphium.github.io&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Bumps nokogiri from 1.18.2 to 1.18.3.Release notesSourced from nokogiri&amp;amp;#39;s releases.v1.18.3 / 2025-02-18Security[CRuby] Vendored libxml2 is updated to v2.13.6 to address CVE-2025-249...&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dependabot[bot]&lt;/code&gt;というユーザがPRを作り&lt;sup id=&quot;fnref1&quot; title=&quot;commitを見るとユーザ名がわかる｡彼の本名は dependabot[bot] &quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dependencies&lt;/code&gt; &lt;code&gt;ruby&lt;/code&gt; というラベルをつける&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;ふむ｡
PRにラベルがついたときにGitHub Actionsを発火させられるので､それをやるとよい｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/yaml/yaml-original.svg&quot; alt=&quot;yaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;.github/workflows/dependabot-hook.yml&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; 
  &lt;span class=&quot;na&quot;&gt;pull_request&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;types&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;labeled&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;ちょっと丁寧に､&lt;code&gt;dependabot&lt;/code&gt;というユーザが&lt;code&gt;dependencies&lt;/code&gt; &lt;code&gt;ruby&lt;/code&gt; ラベルをつけたときに絞る｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/yaml/yaml-original.svg&quot; alt=&quot;yaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;.github/workflows/dependabot-hook.yml&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;hook&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;github.event.label.name == &apos;dependencies&apos; &amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;github.event.label.name == &apos;ruby&apos; &amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;github.actor == &apos;dependabot[bot]&apos;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;runs-on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;ruby&lt;/code&gt;以外にもhookしたい環境がある場合便利ですな｡&lt;/p&gt;&lt;h1 id=&quot;3.+%E3%82%84%E3%82%8B%E3%81%A0%E3%81%91&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#3.+%E3%82%84%E3%82%8B%E3%81%A0%E3%81%91&quot;&gt;3. やるだけ&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;あとはやるだけ｡
bundixでgemsetを更新し､PR branchにcommit &amp;amp; pushする｡&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/yaml/yaml-original.svg&quot; alt=&quot;yaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;.github/workflows/dependabot-hook.yml&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nix run &apos;.#patched-bundix&apos;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# gmsetを更新&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;git config --global user.name &apos;github-actions[bot]&apos;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;git config --global user.email &apos;github-actions[bot]@users.noreply.github.com&apos;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;git commit --all -m &quot;Update gemset.nix via bundix&quot; || echo &quot;No changes to commit&quot;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;git fetch origin&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;git rebase origin/${{ github.event.pull_request.head.ref }} || git merge origin/${{ github.event.pull_request.head.ref }}&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;git push &quot;https://${GITHUB_ACTOR}:${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git&quot; ${{ github.event.pull_request.head.ref }}:refs/heads/${{ github.event.pull_request.head.ref }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;ユーザ名とemailは適当で良いが､無いとcommitできないので設定しておく｡
&lt;code&gt;${GITHUB_ACTOR}&lt;/code&gt; は自動で設定されており､PRのauthorに同じ &lt;code&gt;dependabot[bot]&lt;/code&gt;｡
&lt;code&gt;${{ secrets.GITHUB_TOKEN }}&lt;/code&gt; もGithub Actionsで自動で発行されるトークンで､リポジトリに閉じた権限で使える｡&lt;/p&gt;&lt;p&gt;こういう賢いactionsを使ってもいいかもしれない｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://github.com/marketplace/actions/github-push&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://avatars.githubusercontent.com/u/3618479?s=400&amp;amp;v=4&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://github.com/marketplace/actions/github-push&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GitHub Push - GitHub Marketplace&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Pushing to GitHub repository local changes&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;PRに書き込むために､permissionを設定する必要があるので､やる&lt;/p&gt;&lt;div class=&quot;highlight&quot;&gt;
&lt;span class=&quot;listing-name&quot;&gt;&lt;img class=&quot;listing-icon&quot; src=&quot;https://cdn.jsdelivr.net/gh/devicons/devicon@v2.17.0/icons/yaml/yaml-original.svg&quot; alt=&quot;yaml&quot; onerror=&quot;this.style.display=&apos;none&apos;&quot;&gt;.github/workflows/dependabot-hook.yml&lt;/span&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;permissions&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;write&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;actions&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;write&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;pull-requests&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;write&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;なんか多くね? まあ一旦ええか､一旦…｡&lt;/p&gt;&lt;p&gt;これでPRにhookして自動でgemsetが更新される｡&lt;/p&gt;&lt;div class=&quot;twicard&quot;&gt;
  &lt;span class=&quot;image&quot;&gt;&lt;a href=&quot;https://github.com/Nymphium/nymphium.github.io/pull/74/commits/c2bb00e1782dced565eaa4a3b880722cb2316cbb&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;div&gt;&lt;img src=&quot;https://avatars.githubusercontent.com/in/29110?s=400&amp;amp;v=4&quot;&gt;&lt;/div&gt;&lt;/a&gt;&lt;/span&gt;
  &lt;span class=&quot;txt&quot;&gt;
    &lt;div class=&quot;title&quot;&gt;&lt;a href=&quot;https://github.com/Nymphium/nymphium.github.io/pull/74/commits/c2bb00e1782dced565eaa4a3b880722cb2316cbb&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Bump nokogiri from 1.18.3 to 1.18.4 by dependabot[bot] · Pull Request #74 · Nymphium/nymphium.github.io&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;description&quot;&gt;Bumps nokogiri from 1.18.3 to 1.18.4.Release notesSourced from nokogiri&amp;amp;#39;s releases.v1.18.4 / 2025-03-14Security[CRuby] Vendored libxslt is updated to v1.1.43 to address CVE-2025-248...&lt;/div&gt;
  &lt;/span&gt;
&lt;/div&gt;&lt;p&gt;ええな｡&lt;/p&gt;&lt;h1 id=&quot;4.+%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;&lt;a class=&quot;headerlink&quot; href=&quot;#4.+%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB&quot;&gt;4. おわりに&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Dependabotがhookサポートしてくれねえかな…｡&lt;/p&gt;&lt;hr&gt;&lt;p&gt;この記事は業務時間中に書かれた｡
株式会社eiiconではCIとNixのノウハウが豊富な人材を募集しています｡&lt;/p&gt;&lt;p&gt;本記事で使われたテクニックはプロダクトの開発でも利用されている｡&lt;/p&gt;&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;

&lt;li id=&quot;fn1&quot;&gt;
&lt;p&gt;commitを見るとユーザ名がわかる｡彼の本名は &lt;code&gt;dependabot[bot]&lt;/code&gt; &lt;a href=&quot;#fnref1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;/div&gt;</description>
        <pubDate>Mon, 31 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://nymphium.github.io/2025/03/31/dependabot-hook.html</link>
        <guid isPermaLink="true">https://nymphium.github.io/2025/03/31/dependabot-hook.html</guid>
        
        <category>Dependabot</category>
        
        <category>Nix</category>
        
        <category>GitHub Actions</category>
        
        
      </item>
    
  </channel>
</rss>
