Created
June 18, 2026 11:11
-
-
Save hgiesel/4beb0fd70fa079144077bc17abafb8ba to your computer and use it in GitHub Desktop.
Problem illustrating two-way linked type hierarchies
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use std::collections::HashMap; | |
| use std::hash::Hash; | |
| use std::fmt::Debug; | |
| trait Language { | |
| type PartOfSpeech: PartOfSpeech; | |
| type Slot: Slot; | |
| } | |
| trait PartOfSpeech { | |
| type Language: Language; | |
| type Slot: Slot; | |
| fn inflect(&self, term: &Term<Self::Language>) -> HashMap<Self::Slot, String> | |
| where Self::Slot: Hash; | |
| } | |
| trait Slot { | |
| type Language: Language; | |
| } | |
| #[derive(Debug)] | |
| struct English; | |
| impl Language for English { | |
| type PartOfSpeech = Noun; | |
| type Slot = Singular; | |
| } | |
| #[derive(Debug)] | |
| struct Noun; | |
| impl PartOfSpeech for Noun { | |
| type Language = English; | |
| type Slot = Singular; | |
| fn inflect(&self, term: &Term<Self::Language>) -> HashMap<Self::Slot, String> { | |
| let mut map = HashMap::new(); | |
| map.insert(Singular, term.term.clone()); | |
| map | |
| } | |
| } | |
| #[derive(PartialEq, Eq, Hash, Debug)] | |
| struct Singular; | |
| impl Slot for Singular { | |
| type Language = English; | |
| } | |
| #[derive(Debug)] | |
| struct Term<Lang: Language> { | |
| term: String, | |
| language: Lang, | |
| } | |
| #[derive(Debug)] | |
| struct Lexeme<Part: PartOfSpeech> { | |
| // term: Term<Part::Language>, #!!!!! | |
| term: Term<Part::Language>, | |
| part: Part, | |
| } | |
| trait HasLanguage { | |
| type Language; | |
| } | |
| impl HasLanguage for Noun { | |
| type Language = English; | |
| } | |
| fn process_infl<Lang: Language>(infl: &HashMap<Lang::Slot, String>, term: &Term<Lang>) { | |
| println!("Hi"); | |
| } | |
| fn process_part<Part: PartOfSpeech + Debug>(lexeme: &Lexeme<Part>) | |
| where | |
| Part::Language: Debug, | |
| Part::Slot: Hash, | |
| { | |
| println!("hello! {lexeme:?}"); | |
| let infl = lexeme.part.inflect(&lexeme.term); | |
| // CRASH! No way to make this compile | |
| process_infl(&infl, &lexeme.term); | |
| } | |
| fn main() { | |
| let l = Lexeme { | |
| term: Term { | |
| term: "abc".to_string(), | |
| language: English, | |
| }, | |
| part: Noun, | |
| }; | |
| process_part(&l); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment