タグ

ブックマーク / fumieval.hatenablog.com (54)

  • 意地でも関心を分離する - モナドとわたしとコモナド

    マイクロサービスアーキテクチャにおいて、ある構造化されたデータを、構造を維持したまま別のコンポーネントでも使いたくなる誘惑が存在する。 例えば、ドメインロジックを扱うコンポーネントに「ユーザーの種別(ゲスト、メンバー、管理者)」という概念があり、API トークンの認可情報に含めたいとして、APIトークンを管理するコンポーネントはその概念に関与すべきだろうか。 // 関与しない定義 IssueToken(userType: string, expiresAt: Date): Token // 関与する定義 enum UserType { Guest, Member, Admin, } IssueToken(userType: UserType, expiresAt: Date): Token ここで安易にそうしてしまうと、「ユーザーの種別」の定義が変わったとき——例えば新たに「モデレーター」

    意地でも関心を分離する - モナドとわたしとコモナド
  • Oath: 安全、高速、合成可能な並行処理 - モナドとわたしとコモナド

    TL;DR github.com 並行処理を簡潔かつ安全に記述できるライブラリを作った。ApplicativeDo拡張を使って、以下のようにoathの引数として与えたIOアクションを同時に実行し、結果を集める処理を書ける。いずれかが例外を投げた場合、残りをキャンセルするためリソースを漏らす心配がない。 evalOath $ do a <- oath $ ... b <- oath $ ... f a b 経緯 Haskellは並行処理が得意とされている。事実、軽量スレッド、MVar、STMといった処理系によるサポートが充実しており、HackageのConcurrencyカテゴリには235ものパッケージがあることからもユーザの関心の高さが窺える。 並行処理を実用する上では、単にスレッドをフォークするだけでなく、計算の結果を集める必要がある──Scalaなどで言うFutureに近いものがあると

    Oath: 安全、高速、合成可能な並行処理 - モナドとわたしとコモナド
  • 依存関係と階層構造の軛 - モナドとわたしとコモナド

    21世紀現在のプログラミング言語において、モジュールという機能はほぼ必要不可欠である。ソースコードを分割し、明示的な依存関係を指定する仕組みであるモジュールは、以下のような様々な恩恵をもたらす。 インクリメンタルビルド: モジュールごとにコンパイル結果を保存し、変更されていない部分を再コンパイルするのを防ぐ。 内部の隠蔽: 実装の詳細を隠蔽し、モジュール外から触れないようにする。プログラムの見通しをよくしたり、不正な操作をする機会を減らす。 アーキテクチャの整理: モジュールは他のモジュールを参照できるが、原則として相互参照はしない。依存の向きを定めることで、適切な抽象化と、 それに基づいた実装の分離を促す。 さて、いくらモジュールが便利と言えど、数が増えすぎるとさすがに扱いにくい*1。そのため、ディレクトリの構造をモジュールの階層構造として運用する仕組みが備わっていることが多い。 コンパ

    依存関係と階層構造の軛 - モナドとわたしとコモナド
    igrep
    igrep 2022/05/09
    素晴らしい “ディレクトリ同士の依存関係に着目して考えてみよう。Foo.Bar.A.BがFoo.Baz.C.Dに依存しているとき、「BarがBazに依存している」という情報さえ残せば、それより深い部分の情報は削いでも構わない”
  • 新しいGHC拡張、NoFieldSelectorsについて - モナドとわたしとコモナド

    今まで不満の多かったHaskellのレコードの扱いを改善するための一歩として、NoFieldSelectorsというGHC拡張の実装を進めている。 動機 Haskellにはレコードを定義するための構文がある。 data User = User { userId :: Int , userName :: Text } こう定義すると、各フィールドごとにuserId :: User -> IntとuserName :: User -> Textというゲッターに相当する関数が生成される。これらの関数は特別な意味合いを持っており、以下のレコード操作の構文にも利用できる。 構築 User { userId = 0, userName = "Zero" } パターンマッチ case foo of User { userId = x, userName = name } -> ... 更新 foo {

    新しいGHC拡張、NoFieldSelectorsについて - モナドとわたしとコモナド
    igrep
    igrep 2020/12/29
    "提案者のSimon Hafner氏により、フラグの追加や試験的な実装が作られ、私が実際に機能する段階まであらかた完成させた。現在はレビュー段階にある" ありがとう!どうか希望どおりGHC 9.2に入りますように🙏
  • 自動printfデバッグ - モナドとわたしとコモナド

    関数をデバッグするために、引数と戻り値をそれぞれ表示するというのを誰しもやったことがあると思う。今回はそれを自動化するからくりをHaskellで実装してみる。 目標となるのは、関数が与えられたとき、その引数と結果をターミナルに出力する関数に変換する高階関数、probe :: Traceable a => String -> a -> aである。 testDelay :: Double -> Double -> IO () testDelay dur dur' = threadDelay $ round $ (dur + dur') * 1000000 *Probe> probe "testDelay" testDelay 1 2 testDelay 1.0 2.0: () これは型クラスを活用すればお茶の子さいさいである。以下のように型によって挙動を切り替える関数withTraceData

    自動printfデバッグ - モナドとわたしとコモナド
    igrep
    igrep 2020/10/02
    すばらしい。https://qiita.com/igrep/items/8b62b856ff42d1f51619 を超える秒速でコピペしたい型クラスだ
  • ヘッズのための純粋関数型言語「Lazy SLYR」 - モナドとわたしとコモナド

    ドーモ、変数スレイヤーです。 Brainf*ckめいた派生言語が作られる前に、ニンジャスレイヤーを基にしたニンジャヘッズのための言語「Lazy SLYR」を作ってみた。 ◆Brainfuck派生ではない◆ ◆Lazy K派生でもない◆ ◆独自性重点◆ ◆純粋な◆ Hello, world! イヤーッ!イヤーッ!イヤーッ!グワーッ!グワーッ!グワーッ!イヤーッ!イヤーッ!イヤーッ!グワーッ!イヤーッ!グワーッ!グワーッ!イヤーッ!イヤーッ!イヤーッ!グワーッ!イヤーッ!グワーッ!グワーッ!イヤーッ!イヤーッ!イヤーッ!グワーッ!グワーッ!グワーッ!イヤーッ!イヤーッ!イヤーッ!グワーッ!イヤーッ!グワーッ!グワーッ!イヤーッ!イヤーッ!イヤーッ!グワーッ!グワーッ!グワーッ!イヤーッ!グワーッ!イヤーッ!グワーッ!グワーッ!イヤーッ!イヤーッ!グワーッ!グワーッ!グワーッ!イヤーッ!イヤーッ

    ヘッズのための純粋関数型言語「Lazy SLYR」 - モナドとわたしとコモナド
  • barbies-thで気軽にHKDを堪能しよう [Haskell AdC 14] - モナドとわたしとコモナド

    ミーハーな読者なら、barbiesというライブラリをご存知の方も多いと思う。そう、HKDを扱う定番ライブラリだ。HKDは、同アドベントカレンダーにも寄稿されている他、Haskell Dayでも紹介された(https://assets.adobe.com/public/b93f214d-58c2-482f-5528-a939d3e83660)注目の技法だ。Higher-Kinded Data (HKD) について - Qiita HKDは、一番簡単な場合であるはずのIdentityを使うと着脱が面倒になるという問題がよく知られている。Data.Barbie.BareモジュールのWearという型族を使って定義すれば、それを簡単にはがせ、普通のレコードと全く同じように使える。 data Barbie t f = Barbie { name :: Wear t f String , age ::

    barbies-thで気軽にHKDを堪能しよう [Haskell AdC 14] - モナドとわたしとコモナド
    igrep
    igrep 2019/12/26
    GenericsよりもTHの方がコンパイル速いってのがね...
  • 最強にして最速のビルダー、mason - モナドとわたしとコモナド

    Haskell Advent Calendar 2019 5日目 この冬、神速のサンタクロースがやってくる—— Haskellにおいて、バイト列の表現はByteStringが定番である。ByteStringはPinned領域に直接格納され、空間効率はリストに比べればはるかに良い。しかし、Pinned領域にあるとヒープフラグメンテーションが起こりやすくなるということでもあり、細かい文字列をつなぎ合わせるような使い方はパフォーマンスに悪影響が及ぶ。そのような問題を避けるため、ビルダーと呼ばれる構造が用意されている。 Data.ByteString.Builderは、word8 42 <> byteString "hello" <> doubleLE 42のように細かいプリミティブを連結し、toLazyByteStringを呼ぶと最後にByteStringを一気に鋳出せるという仕組みである。By

    最強にして最速のビルダー、mason - モナドとわたしとコモナド
    igrep
    igrep 2019/12/05
    すごい。内部構造はむしろこれまでよりきれいになっているだろうにここまで高速化できるとは。やっぱensureの融合変換がミソなんだろうか。
  • 正格フラグ、バンパターン、正格版関数・データ構造 - モナドとわたしとコモナド

    Haskellスペースリーク Advent Calendar 2015 9日目 Haskellerとて、時には厳しくならなければいけないこともある―― @fumieval, 2015 Haskellは遅延評価を基としているため、場合によっては未評価の式が積もり非効率な状況に陥ることがある。これを防ぐため、部分的に正格評価にするための仕組みが用意されている。もちろんこれらは闇雲に使えばよいというものではない。使うべきポイントを把握し、これらを見逃さないようにしよう。 この記事では、それらの機能の正しい使い方、間違った使い方を紹介していこう。 カウンター・カウンターズ・サンクス 条件を満たす要素の個数とそうでない要素をそれぞれカウントするプログラムについて考える。アキュムレータ(ループの中で積み上げていく変数)は正格にしないといけないらしいので、BangPatterns拡張を使ってみた。どん

    正格フラグ、バンパターン、正格版関数・データ構造 - モナドとわたしとコモナド
  • 単純で頑強なメッセージングシステム、franz - モナドとわたしとコモナド

    Haskell製の新しいメッセージングシステムfranz(フランツ)の紹介。 github.com 背景 取引所にあるマシンで取引プログラムを実行するのが我々の仕事だが、朝8時に起動したらあとは昼寝したり酒を飲んだりというわけにはいかない。モニタリングしたり、分析のためにデータを残しておく必要がある。そのため、プログラムによって解析しやすい形でログを出力する。 今までは複数の種類のレコードをシリアライズし、一つのファイルに連結させる独自のフォーマットを10年近く使っていたが、書いていて恥ずかしくなるような多数の問題を抱えていた。 柔軟性が乏しい: 32bit整数や文字列などの単純な値しか格納できず、例えばレコードを含むレコードなどを表現できない。その結果、複雑なデータは一旦文字列に変換するような運用がされており、そのプリティプリンタやパーサは十分にテストされていない。 コードがまとまってい

    単純で頑強なメッセージングシステム、franz - モナドとわたしとコモナド
    igrep
    igrep 2019/09/07
    すげぇなぁ。後で詳しく読もう / 読んだ。謎のパラメーターf, リストでよくね?とも思ったけど、ユーザー自身でindexの名前の数とindexの数が一致することを保証できるってことか。
  • Traversable API - モナドとわたしとコモナド

    与えられたConnectionを通じて、指定したKeyに対応するByteStringを取り出すような、シンプルなKey-ValueストアのAPIを考えてみよう。 type Key = ByteString fetchOne :: Connection -> Key -> IO ByteString ネットワーク越しにたくさんのデータを取得したいとき、何度もこれを呼び出していては効率が悪い。一度にまとめて取り出せるように拡張するなら、このように書ける。 fetchMany :: Connection -> [Key] -> IO [ByteString] 悪くはないが、この型はたとえば「["foo", "bar"]を要求したのに返ってきたのは[]」のような振る舞いを許してしまうため、使い手に不必要なパターンマッチを強いる。だが、リスト[]にちょっとした一般化を施すだけでそれを防ぐことが可能だ

    Traversable API - モナドとわたしとコモナド
  • 特級シリアライズライブラリ、winery 1.0解禁 - モナドとわたしとコモナド

    fumieval.hatenablog.com あれから9ヶ月…wineryのバージョン1.0をついにリリースした。 前回までのあらすじ データの保存や通信に直列化は不可欠の概念である。 binaryなどの直列化ライブラリは、レコードのフィールド名などの情報が欠けており、構造が変わると互換性を持たせることができない。 一方、JSONやCBORなどのフォーマットで愚直にフィールド名などを残すと極めて冗長になり、時間・空間効率が悪い。 コード生成が前提のProtobufなどはHaskellの既存のデータ構造との相性がよくない。 そんな現状に殴り込みをかけたのがwineryだ。値を「スキーマ」と「データ」に分割して保存することによって、冗長性を避けつつ、メタデータを保持させることができる。wineryは最強のライブラリとなりうるか…? 特徴と特長 JSON, MessagePack, CBORな

    特級シリアライズライブラリ、winery 1.0解禁 - モナドとわたしとコモナド
    igrep
    igrep 2019/03/27
    "データにroleが欠けている場合の振る舞いも、ApplicativeDo記法を用いてカスタマイズができる。なんとメールアドレスがexample.comで終わっていれば自動で昇格するといった芸当も可能" バイナリ版ヘッダ付きCSVみたいな?
  • 旅のチェックリスト - モナドとわたしとコモナド

    筆者が旅に出る際に確認する項目をまとめた。 事前の準備 渡航ビザ: 必要な場合もあるので事前に確かめよう。 ESTA(アメリカの場合): どんな理由であれUSに入国する場合申請する必要がある。大抵すぐ承認されるが、遅くとも出発の72時間前に済ませるべきである。 宿: 好みに応じてホテルでもAirBnBなどで民泊を予約しても。後者はキッチンが用意されているところもある。 交通手段: 電車は大抵の場合当日で大丈夫だが、もちろん船舶や航空機の場合は予約が必須である。 冷蔵庫の整理: 日持ちしないものは消費してしまおう。 携帯するもの 財布: 財布は現金やカードを収納する。リスク回避の観点から財布は省きセキュリティポーチで代用することもできる。 鍵: 自宅を施錠、および帰りに解錠するのに必要である。こちらもリスク回避のため、自宅の鍵のみを持っていくという選択もある。 交通系ICカード: 空港や港に

    旅のチェックリスト - モナドとわたしとコモナド
    igrep
    igrep 2019/02/15
  • ある期間内に更新されたデータを素早く検索できるモデル - モナドとわたしとコモナド

    特定の技術とは関係ない、誰でも思いつきそうな、でも便利なお話。 こんなケースを考えてみよう。 人気のトレーディングカードゲームAugur Unlimitedを扱うショップ「しらさぎ商店」では、1000種類にも及ぶカードの買い取り・販売をしている。記録のため、カードごとに日時、価格、在庫数などをまとめたレコードを毎日データベースに書き込んでいる。 新着・売り切れや、価格の変化などを、指定された期間について一覧で表示するようなWebページを作りたいとオーナーは考えた。しかし、ユーザーからの要求ごとに全データの差分を取るのは、あまり効率的な手段とはいえない。レアなカードでもない限り価格は一定であることが多いからだ。 どうすれば更新されたものだけを効率よく取り出せるだろうか? 答えはシンプルで、「日時」を「作成日時」と「終了日時」に分け、価格などが変わった時だけ新しくレコードを作成すると同時に、前

    ある期間内に更新されたデータを素早く検索できるモデル - モナドとわたしとコモナド
  • 戊戌の追憶 - モナドとわたしとコモナド

    この記事は、筆者が過ごした2018年を簡潔に振り返り、その経験を糧とすることを狙う。 1月 第二鰓弓由来側頸嚢胞という先天異常が原因で首が化膿し、激痛に苦しんでいた。対人関係のトラブルなどもあり軽い錯乱状態にあったのか、自分が知らない間に高い買い物をすることがあった。 drinkery: Boozy streaming library というストリーム処理ライブラリを作った。当初はすべて酒関係の用語を用いていたが、批判を受けてそこはやめた。今思えばそれで正解だった気がする。 パフォーマンスはモナディックなAPIを持つライブラリの中ではトップクラスで、双方向性や多入力多出力のような発展的な機能もあるが、ListTが正しく効率的に実装されているのがなによりの魅力である。ListTのために時々使っている。 Drinkery the boozy streaming library - School

    戊戌の追憶 - モナドとわたしとコモナド
    igrep
    igrep 2018/12/28
    いろいろ大変な目に遭いながらどんどん新しいもの作っててすごいなぁ...
  • Elias-Fano encoding: 単調増加する数列をほぼ簡潔に表現する - モナドとわたしとコモナド

    Haskell Advent Calendar 2018 20日目 単調増加する自然数の列を、最低限のビット数で表現するための興味深いテクニックと、Haskellによる実装を紹介する。 Elias-Fano encoding この手法は、簡潔データ構造に分類されるもの一つであるが、厳密には条件を満たさないため疑似簡潔データ構造と呼ばれる。1970年代、Peter EliasとRobert Mario Fanoによって独立して発見された。 例題として1, 1, 4, 10, 17, 22, 23, 30という列をエンコードしてみよう。まず、それぞれの数を上位3ビットと下位2ビットに分割する。列の長さをNとしたとき、上位のビット数はとする。 上位ビットの列は000 000 001 010 100 101 101 111となる。これをヒストグラムのようにして23個のビンに分ける。 000: 2個

  • 「名前の束縛」という名の束縛 - モナドとわたしとコモナド

    実用的なプログラミングにおいて、名前と概念を結びつける「束縛」はほぼ必須の概念である。しかし、その言葉には大きな誤解と混乱が根付いていた。 事の発端となったのは「Haskellにおいては、変数は値を代入するものではなく、値に束縛するものである」という議論である*1 *2。しかし、これは大きな誤解を孕んでいる。言葉の定義に立ち返ってその誤解を解いていこう。 束縛とバインディング 実は「束縛」には二つの意味がある。一つは、数学的な意味での変数の束縛*3、もう一つは、識別子と実体の結合という意味での束縛*4だ。 前者は変数の導入と言い換えることもできる。ラムダ計算におけるラムダ抽象と変数の関係もこれである。重要なのは、これはあくまで変数とそれを導入する抽象の関係であり、変数と実体の関係ではないことだ。 「AをBに束縛する」と言った場合後者で、プログラミングの文脈ではこちらを耳にすることが多いだろ

    「名前の束縛」という名の束縛 - モナドとわたしとコモナド
    igrep
    igrep 2018/10/31
    さすが仕事が早いなぁ。Rubyにおけるbindingオブジェクトも、ラムダ計算の束縛じゃない方のバインディングであることがよく分かる
  • 日持ちする直列化のためのライブラリ「winery」 - モナドとわたしとコモナド

    人類は、酒と共に発展してきたと言っても過言ではない。穀物や果実などを酒に変換することにより、糖を除く栄養を保ったまま、高い保存性を持たせることができる。酒は人々の喉を潤し、時に薬として使われた。 プログラミングにおいても、終了したら消えてしまうデータを、保存性の高いバイト列に変えたい場面がよくある。そのような操作を直列化(シリアライズ)と呼び、いくつかのアプローチが存在する。 コード生成タイプ Protocol Buffers、cap'n'protoなど データの構造を記述する言語(スキーマ)から、データ構造およびシリアライザ・デシリアライザをコードごと生成する。幅広い言語で使える一方、作れる構造が限られており、定義済みの構造にも使えないので、Haskellのような言語とは相性があまりよくない。 互換性を保つ機能が充実していることが多い。 汎用フォーマットタイプ CBOR、MessageP

    日持ちする直列化のためのライブラリ「winery」 - モナドとわたしとコモナド
    igrep
    igrep 2018/06/03
    “生成元のプログラムが変わったり失われたりしても、データがどのような構造を持っているか知ることができる。フィールド名などのメタデータを一箇所に集約”まさにいいとこ取りだ
  • HaskellでDiscordのBotを作る - モナドとわたしとコモナド

    Discordはゲーミング向けのテキストチャットと音声通話を兼ねるプラットフォームであり、「テキストチャンネル」と「ボイスチャンネル」の二種を好きなだけ作ることができる。もちろん音声を全チャンネルに常時垂れ流すわけには行かないので、通話するにはボイスチャンネルに参加するという手順を踏む必要がある。しかし、例えば誰かがやっているゲームに混ざろうとしてボイスチャンネルに参加しても、チャンネル外のユーザーにはいかなる通知も発生しないため、気づかれないままのことがよくある。 そこで、ボイスチャンネルに参加したとき、テキストチャンネルにその旨を投稿するボットを用意すれば、気軽に通話の合図を送れる。全員に通話の意思を表明でき、Skypeの着信のように邪魔にもならないので、少人数のグループにとって極めて有用である。 Discordは柔軟なAPIを用意しているため、比較的容易にそのようなボットを開発できる

    HaskellでDiscordのBotを作る - モナドとわたしとコモナド
  • ガバガバAltJSを作った(言語実装 Advent Calendar 2017) - モナドとわたしとコモナド

    qiita.com JavaScriptを書いていると、頻出する継続渡しのリフレインにうんざりさせられる。 foo.bar(function(result){ qux.baz(function(data){ hoge(function(r){ ... }); }); }); そこで、腕試しに継続モナドをベースにしたAltJS、jatkoを作った。フィンランド語で「継続」という意味だ(継続戦争から知った人も多いだろう)。しかし、なんの考えもなしに653行Haskellを書いた結果ガバガバな言語になってしまった。 Hello, world Haskellにだいぶ近いのでなんとなく読めるはず。 infixr 1 -> infixr 0 $ ($) = \x -> x constructor String : Type constructor (->) : Type -> Type -> Type

    ガバガバAltJSを作った(言語実装 Advent Calendar 2017) - モナドとわたしとコモナド
    igrep
    igrep 2017/12/24
    "特に面白いのは、「改行をスキップしない」のようなパーサーの変化をモナド変換子によって実現しているところだ。これは「モナド変換子の代替」とされるExtensible effectsでは素直にはいかない"