Rustで圏論(1)
発端
圏論を勉強しているのだが、本格的に書籍を買ってから約一年になる。圏論の勉強では、実際に手を動かして図式を書かないとかなり効率が悪くて、ものぐさな自分もさすがにペンでお絵かきしていた。が、だんだんそれもイヤになってしまい、せっかくなのでiPad ProにApple Pencilで図を描き始めた。これはいい。標準のメモアプリで、図とテキストが共存できるのがめちゃ便利だ。ところが今度は図の変形や、証明を追う段階になるとこれでもつらい。ということでプログラミングで解決したくなった。ごぶさたなのでRustで書きたくなった。
というわけで、リハビリを兼ねて書き始めた。めちゃくちゃアホっぽいが、まずはこれでいい。少しずつやっていく所存である。
struct Category { objects: Vec<String>, arrows: Vec<String> } fn main() { let category = Category { objects: vec![ "A".to_string(), "B".to_string(), "C".to_string() ], arrows: vec![ "f: A -> B".to_string(), "g: A -> C".to_string(), "h: B -> C".to_string() ] }; }
さすがに、射の方をそのまま文字列で持っているのは変更。でも一気にコードの雰囲気は変わってくる。
ひとまず射をそれっぽく表示するようにDisplay
をimplする。
use std::fmt::Display; use std::collections::HashMap; type Arrows = HashMap<String, (String, String)>; struct Category { objects: Vec<String>, arrows: Arrows } impl Display for Category { fn fmt(&self, dest: &mut std::fmt::Formatter) -> std::fmt::Result { let mut arrow_texts = vec![]; for (k, v) in &self.arrows { arrow_texts.push(format!("{}: {} -> {}", k, v.0, v.1)); } write!(dest, "objects: {:?} \n arrows: {:?}", self.objects, arrow_texts) } } fn insert_arrow(arrows: &mut Arrows, name: &str, domain: &str, codomain: &str) { arrows.insert(name.to_string(), (domain.to_string(), codomain.to_string())); } fn main() { let mut arrows = HashMap::new(); insert_arrow(&mut arrows, "f", "A", "B"); insert_arrow(&mut arrows, "g", "A", "C"); insert_arrow(&mut arrows, "h", "B", "C"); let category = Category { objects: vec![ "A".to_string(), "B".to_string(), "C".to_string() ], arrows: arrows }; println!("{}", category); }
というわけで、実行すると以下が表示される。
objects: ["A", "B", "C"] arrows: ["g: A -> C", "f: A -> B", "h: B -> C"]
ちなみに、図式で書くと以下のようになる。