Skip to content

Instantly share code, notes, and snippets.

@ElectricCoffee
Created September 19, 2018 17:36
Show Gist options
  • Save ElectricCoffee/749411b129d6f331a113a6d2b452117d to your computer and use it in GitHub Desktop.
Save ElectricCoffee/749411b129d6f331a113a6d2b452117d to your computer and use it in GitHub Desktop.
A test of phantom types in Rust. A bit more cumbersome than Haskell, but definitely doable.
use std::marker::PhantomData;
use std::convert::From;
// Define the empty temperature markers
#[derive(Debug, Copy, Clone)] struct C;
#[derive(Debug, Copy, Clone)] struct F;
// Temperature Struct with Phantom Data
#[derive(Debug, Copy, Clone)]
struct Temp<T> {
temp: f64,
unit: PhantomData<T>,
}
impl<T> Temp<T> {
fn new(temp: f64) -> Temp<T> {
Temp { temp, unit: PhantomData }
}
}
// Conversion from F to C
impl From<Temp<F>> for Temp<C> {
// [°C] = ([°F] − 32) × ​5⁄9
fn from(temp: Temp<F>) -> Self {
let f = temp.temp;
Temp::new((f - 32.0) * 5.0 / 9.0)
}
}
// Conversion from C to F
impl From<Temp<C>> for Temp<F> {
//[°F] = [°C] × ​9⁄5 + 32
fn from(temp: Temp<C>) -> Self {
let c = temp.temp;
Temp::new(c * 9.0 / 5.0 + 32.0)
}
}
fn main() {
let c: Temp<C> = Temp::new(20.0);
let f: Temp<F> = c.into();
println!("Testing conversion from 20°C to °F");
println!("°C: {:?}", c);
println!("°F: {:?}", f);
let f: Temp<F> = Temp::new(-40.0);
let c: Temp<C> = f.into();
println!("Testing conversion from -40°F to °C");
println!("°F: {:?}", f);
println!("°C: {:?}", c);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment