I've seen this old article (that contains obsolete types and syntax) about phantom types:
https://bluishcoder.co.nz/2013/08/15/phantom_types_in_rust.html
So I've tried to update and improve the code ( https://bluishcoder.co.nz/rust/pt/test2.rs ) like this:
mod tis {
use std::marker::PhantomData;
use std::fmt;
pub enum T<A> {
Ti(i32, PhantomData<A>),
Ts(String, PhantomData<A>),
}
pub type Ti32 = T<i32>;
pub type TString = T<String>;
impl T<i32> {
pub fn new(i: i32) -> Self { T::Ti(i, PhantomData::<i32>) }
pub fn plus(self, b: T<i32>) -> Self {
if let (T::Ti(i1, _), T::Ti(i2, _)) = (self, b) {
return Ti32::new(i1 + i2);
}
panic!();
}
}
impl T<String> {
pub fn new(s: String) -> Self { T::Ts(s, PhantomData::<String>) }
pub fn concat(self, b: T<String>) -> Self {
if let (T::Ts(s1, _), T::Ts(s2, _)) = (self, b) {
return TString::new(s1 + &s2);
}
panic!();
}
}
impl<U> fmt::Debug for T<U> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&T::Ti(i, _) => write!(f, "i32: {}", i),
&T::Ts(ref s, _) => write!(f, "str: {}", s),
}
}
}
}
fn main() {
use tis::*;
let d1 = Ti32::new(1);
let d2 = Ti32::new(2);
let x = d1.plus(d2);
println!("{:?}", x);
let d1 = TString::new("Hello, ".into());
let d2 = TString::new("World".into());
let y = d1.concat(d2);
println!("{:?}", y);
//let z = x.concat(y); // Compilation error.
}
(Inside the tis module the fmt() is not public, but the printf give no errors, do you know why?)
Several people have suggested to turn enum members into types ( https://github.com/rust-lang/rfcs/issues/754 ). If that happens in Rust then does it allow to rewrite that code like this?
use std::fmt;
enum T { Ti(i32), Ts(String) }
impl T::Ti {
fn plus(self, b: T::Ti) -> Self {
T::Ti(self.0 + b.0)
}
}
impl T::Ts {
fn concat(self, b: T::Ts) -> Self {
T::Ts(self.0 + &b.0)
}
}
impl fmt::Debug for T {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&T::Ti(i) => write!(f, "i32: {}", i),
&T::Ts(ref s) => write!(f, "str: {}", s),
}
}
}
fn main() {
let d1 = T::Ti(1);
let d2 = T::Ti(2);
let x = d1.plus(d2);
println!("{:?}", x);
let d1 = T::Ts("Hello, ".into());
let d2 = T::Ts("World".into());
let y = d1.concat(d2);
println!("{:?}", y);
//let z = x.concat(y); // Compilation error.
}
If this is right then it's a significant improvement for the code.