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"]

ちなみに、図式で書くと以下のようになる。

f:id:ironoir:20180824172527p:plain