Skip to content

Instantly share code, notes, and snippets.

@justanotherdot
Last active October 2, 2020 01:37
Show Gist options
  • Save justanotherdot/25c479e3cfdbe5c93343bb91c44df514 to your computer and use it in GitHub Desktop.
Save justanotherdot/25c479e3cfdbe5c93343bb91c44df514 to your computer and use it in GitHub Desktop.
#[derive(Debug)]
struct Holder<T: PrimitiveType>(T::Native);
#[derive(Debug)]
struct Float64 {}
#[derive(Debug)]
struct Int64 {}
#[derive(Debug)]
struct Int32 {}
trait NativeType {}
impl NativeType for f64 {}
impl NativeType for i64 {}
impl NativeType for i32 {}
trait PrimitiveType {
type Native: NativeType;
}
impl PrimitiveType for Float64 {
type Native = f64;
}
impl PrimitiveType for Int64 {
type Native = i64;
}
impl PrimitiveType for Int32 {
type Native = i32;
}
fn promote_float_to_int(holder: Holder<Float64>) -> Holder<Int64> {
let Holder(x) = holder;
Holder(x as i64)
}
fn promote_int_to_float(holder: Holder<Int64>) -> Holder<Float64> {
let Holder(x) = holder;
Holder(x as f64)
}
fn map<A, B, P, Q, F>(holder: Holder<A>, f: F) -> Holder<B>
where
A: PrimitiveType<Native = P>,
B: PrimitiveType<Native = Q>,
P: NativeType,
Q: NativeType,
F: Fn(P) -> Q,
{
let Holder(x) = holder;
Holder(f(x))
}
// NB. Given these implmementations, this is probably better named `Cast`.
trait Promote<A> {
fn promote(x: A) -> Self;
}
impl Promote<i64> for f64 {
fn promote(x: i64) -> f64 {
x as f64
}
}
impl Promote<f64> for i64 {
fn promote(x: f64) -> i64 {
x as i64
}
}
fn promote<A, B, P, Q>(holder: Holder<A>) -> Holder<B>
where
A: PrimitiveType<Native = P>,
B: PrimitiveType<Native = Q>,
P: NativeType,
Q: NativeType + Promote<P>,
{
let Holder(x) = holder;
Holder(Promote::promote(x))
}
fn promote_from<A, B, P, Q>(holder: Holder<A>) -> Holder<B>
where
A: PrimitiveType<Native = P>,
B: PrimitiveType<Native = Q>,
P: NativeType,
Q: NativeType + From<P>,
{
let Holder(x) = holder;
Holder(From::from(x))
}
fn main() {
let x: Holder<Float64> = Holder(12.0);
dbg!(&x);
let y = promote_float_to_int(x);
dbg!(&y);
let z = promote_int_to_float(y);
dbg!(&z);
let a: Holder<Int64> = Holder(42);
dbg!(&a);
let b: Holder<Float64> = map(a, |x| x as f64);
dbg!(&b);
let c: Holder<Int64> = map(b, |x| x as i64);
dbg!(&c);
let a: Holder<Int32> = Holder(42);
dbg!(&a);
let b: Holder<Float64> = promote_from(a);
dbg!(&b);
// let c: Holder<Int32> = promote(b);
// dbg!(&c);
let a: Holder<Int64> = Holder(42);
dbg!(&a);
let b: Holder<Float64> = promote(a);
dbg!(&b);
let c: Holder<Int64> = promote(b);
dbg!(&c);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment