{"id":13995100,"url":"https://github.com/Centril/refl","last_synced_at":"2025-07-22T21:31:59.085Z","repository":{"id":57659303,"uuid":"119264510","full_name":"Centril/refl","owner":"Centril","description":"Provides a Refl encoding in Rust","archived":false,"fork":false,"pushed_at":"2023-04-06T04:53:38.000Z","size":21,"stargazers_count":68,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-16T03:33:17.431Z","etag":null,"topics":["gadt","propositional-logic","rust","type-system"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Centril.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-01-28T14:14:01.000Z","updated_at":"2025-03-29T03:35:21.000Z","dependencies_parsed_at":"2024-01-15T19:43:35.990Z","dependency_job_id":"4dc78972-21b9-473e-8af9-5f98c25e8bfd","html_url":"https://github.com/Centril/refl","commit_stats":{"total_commits":19,"total_committers":2,"mean_commits":9.5,"dds":"0.052631578947368474","last_synced_commit":"5061f33d9194a1efd1df79045a28d4d7bd1ff0a2"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Centril/refl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Centril%2Frefl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Centril%2Frefl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Centril%2Frefl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Centril%2Frefl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Centril","download_url":"https://codeload.github.com/Centril/refl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Centril%2Frefl/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265648677,"owners_count":23804697,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gadt","propositional-logic","rust","type-system"],"created_at":"2024-08-09T14:03:15.039Z","updated_at":"2025-07-22T21:31:58.817Z","avatar_url":"https://github.com/Centril.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# `refl`\n\n[![Build Status](https://travis-ci.org/Centril/refl.svg?branch=master)](https://travis-ci.org/Centril/refl)\n[![](http://meritbadge.herokuapp.com/refl)](https://crates.io/crates/refl)\n\nProvides a `refl` encoding which you can use to provide a proof\nwitness that one type is equivalent (identical) to another type.\nYou can use this to encode a subset of what GADTs allow you to in Haskell.\n\nThis is encoded as:\n\n```rust\nuse std::mem;\nuse std::marker::PhantomData;\n\npub struct Id\u003cS: ?Sized, T: ?Sized\u003e(PhantomData\u003c(*mut S, *mut T)\u003e);\n\nimpl\u003cT: ?Sized\u003e Id\u003cT, T\u003e { pub const REFL: Self = Id(PhantomData); }\n\npub fn refl\u003cT: ?Sized\u003e() -\u003e Id\u003cT, T\u003e { Id::REFL }\n\nimpl\u003cS: ?Sized, T: ?Sized\u003e Id\u003cS, T\u003e {\n    /// Casts a value of type `S` to `T`.\n    ///\n    /// This is safe because the `Id` type is always guaranteed to\n    /// only be inhabited by `Id\u003cT, T\u003e` types by construction.\n    pub fn cast(self, value: S) -\u003e T where S: Sized, T: Sized {\n        unsafe {\n            // Transmute the value;\n            // This is safe since we know by construction that\n            // S == T (including lifetime invariance) always holds.\n            let cast_value = mem::transmute_copy(\u0026value);\n    \n            // Forget the value;\n            // otherwise the destructor of S would be run.\n            mem::forget(value);\n    \n            cast_value\n        }\n    }\n\n    // ..\n}\n```\n\nIn Haskell, the `Id\u003cA, B\u003e` type corresponds to:\n\n```haskell\ndata a :~: b where\n    Refl :: a :~: a\n```\n\nHowever, note that you must do the casting manually with `refl.cast(val)`.\nRust will not know that `S == T` by just pattern matching on `Id\u003cS, T\u003e`\n(which you can't do).\n\n# Limitations\n\nPlease note that Rust has no concept of higher kinded types (HKTs) and so\nwe can not provide the general transformation `F\u003cS\u003e -\u003e F\u003cT\u003e` given that\n`S == T`. With the introduction of generic associated types (GATs), it\nmay be possible to introduce more transformations.\n\n# Example - A GADT-encoded expression type\n\n```rust\nextern crate refl;\nuse refl::*;\n\ntrait Ty { type Repr: Copy + ::std::fmt::Debug; }\n\n#[derive(Debug)]\nstruct Int;\nimpl Ty for Int { type Repr = usize; }\n\n#[derive(Debug)]\nstruct Bool;\nimpl Ty for Bool { type Repr = bool; }\n\n#[derive(Debug)]\nenum Expr\u003cT: Ty\u003e {\n    Lit(T::Repr),\n    Add(Id\u003cusize, T::Repr\u003e, Box\u003cExpr\u003cInt\u003e\u003e, Box\u003cExpr\u003cInt\u003e\u003e),\n    If(Box\u003cExpr\u003cBool\u003e\u003e, Box\u003cExpr\u003cT\u003e\u003e, Box\u003cExpr\u003cT\u003e\u003e),\n}\n\nfn eval\u003cT: Ty\u003e(expr: \u0026Expr\u003cT\u003e) -\u003e T::Repr {\n    match *expr {\n        Expr::Lit(ref val) =\u003e\n            *val,\n        Expr::Add(ref refl, ref l, ref r) =\u003e\n            refl.cast(eval(\u0026*l) + eval(\u0026*r)),\n        Expr::If(ref c, ref i, ref e) =\u003e\n            if eval(\u0026*c) { eval(\u0026*i) } else { eval(\u0026*e) },\n    }\n}\n\nfn main() {\n    let expr: Expr\u003cInt\u003e =\n        Expr::If(\n            Box::new(Expr::Lit(false)),\n            Box::new(Expr::Lit(1)),\n            Box::new(Expr::Add(\n                refl(),\n                Box::new(Expr::Lit(2)),\n                Box::new(Expr::Lit(3)),\n            ))\n        );\n\n    assert_eq!(eval(\u0026expr), 5);\n}\n```\n\n## Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you, as defined in the Apache-2.0 license, shall\nbe dual licensed as above, without any additional terms or conditions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCentril%2Frefl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FCentril%2Frefl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCentril%2Frefl/lists"}