#等价 #类型级别 #命题

refl

提供了一种 refl 编码,您可以使用它来提供一种证明证据,表明一种类型与另一种类型等价(相同)。您可以使用它来编码 Haskell 中 GADTs 允许您编码的一个子集。

6个版本

0.2.1 2020年2月24日
0.2.0 2019年3月23日
0.1.3 2019年3月23日
0.1.2 2018年2月4日
0.1.1 2018年1月28日

Rust模式中排名572

Download history 50/week @ 2023-11-25 12/week @ 2023-12-02 13/week @ 2023-12-09 23/week @ 2023-12-16 29/week @ 2023-12-23 16/week @ 2024-01-06 30/week @ 2024-01-13 6/week @ 2024-01-20 6/week @ 2024-01-27 11/week @ 2024-02-03 24/week @ 2024-02-10 34/week @ 2024-02-17 41/week @ 2024-02-24 38/week @ 2024-03-02 17/week @ 2024-03-09

每月下载量134
12个crate(2个直接)中使用

MIT/Apache

15KB
69

refl

Build Status

提供了一种 refl 编码,您可以使用它来提供一种证明证据,表明一种类型与另一种类型等价(相同)。您可以使用它来编码 Haskell 中 GADTs 允许您编码的一个子集。

编码如下

use std::mem;
use std::marker::PhantomData;

pub struct Id<S: ?Sized, T: ?Sized>(PhantomData<(*mut S, *mut T)>);

impl<T: ?Sized> Id<T, T> { pub const REFL: Self = Id(PhantomData); }

pub fn refl<T: ?Sized>() -> Id<T, T> { Id::REFL }

impl<S: ?Sized, T: ?Sized> Id<S, T> {
    /// Casts a value of type `S` to `T`.
    ///
    /// This is safe because the `Id` type is always guaranteed to
    /// only be inhabited by `Id<T, T>` types by construction.
    pub fn cast(self, value: S) -> T where S: Sized, T: Sized {
        unsafe {
            // Transmute the value;
            // This is safe since we know by construction that
            // S == T (including lifetime invariance) always holds.
            let cast_value = mem::transmute_copy(&value);
    
            // Forget the value;
            // otherwise the destructor of S would be run.
            mem::forget(value);
    
            cast_value
        }
    }

    // ..
}

在 Haskell 中,类型 Id<A, B> 对应于

data a :~: b where
    Refl :: a :~: a

但是请注意,您必须手动使用 refl.cast(val) 进行类型转换。Rust 仅通过在 Id<S, T>(您不能这样做)上进行模式匹配,并不能知道 S == T

限制

请注意,Rust 没有高阶类型(HKTs)的概念,因此我们无法在 F<S> -> F<T> 给定 S == T 的情况下提供通用转换。随着泛型关联类型(GATs)的引入,可能可以引入更多转换。

示例 - GADT 编码的表达式类型

extern crate refl;
use refl::*;

trait Ty { type Repr: Copy + ::std::fmt::Debug; }

#[derive(Debug)]
struct Int;
impl Ty for Int { type Repr = usize; }

#[derive(Debug)]
struct Bool;
impl Ty for Bool { type Repr = bool; }

#[derive(Debug)]
enum Expr<T: Ty> {
    Lit(T::Repr),
    Add(Id<usize, T::Repr>, Box<Expr<Int>>, Box<Expr<Int>>),
    If(Box<Expr<Bool>>, Box<Expr<T>>, Box<Expr<T>>),
}

fn eval<T: Ty>(expr: &Expr<T>) -> T::Repr {
    match *expr {
        Expr::Lit(ref val) =>
            *val,
        Expr::Add(ref refl, ref l, ref r) =>
            refl.cast(eval(&*l) + eval(&*r)),
        Expr::If(ref c, ref i, ref e) =>
            if eval(&*c) { eval(&*i) } else { eval(&*e) },
    }
}

fn main() {
    let expr: Expr<Int> =
        Expr::If(
            Box::new(Expr::Lit(false)),
            Box::new(Expr::Lit(1)),
            Box::new(Expr::Add(
                refl(),
                Box::new(Expr::Lit(2)),
                Box::new(Expr::Lit(3)),
            ))
        );

    assert_eq!(eval(&expr), 5);
}

贡献

除非您明确声明,否则根据 Apache-2.0 许可证定义,您提交的任何贡献,有意将其包含在作品中的,应按上述方式双重许可,而不附加任何额外的条款或条件。

无运行时依赖