lean4-htt/src/Init/Dynamic.lean
2022-10-19 09:28:08 -07:00

96 lines
2.8 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2022 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Gabriel Ebner
-/
prelude
import Init.Core
open Lean
-- Implementation detail of TypeName, since classes cannot be opaque
private opaque TypeNameData (α : Type u) : NonemptyType.{0} :=
⟨Name, inferInstance⟩
/--
Dynamic type name information.
Types with an instance of `TypeName` can be stored in an `Dynamic`.
The type class contains the declaration name of the type,
which must not have any universe parameters
and be of type `Sort ..` (i.e., monomorphic).
The preferred way to declare instances of this type is using the derive
handler, which will internally use the unsafe `TypeName.mk` function.
Morally, this is the same as:
```lean
class TypeName (α : Type) where unsafe mk ::
typeName : Name
```
-/
@[nospecialize]
class TypeName (α : Type u) where private mk' ::
private data : (TypeNameData α).type
instance : Nonempty (TypeName α) := (TypeNameData α).property.elim (⟨⟨·⟩⟩)
/--
Creates a `TypeName` instance.
For safety, it is required that the constant `typeName` is definitionally equal
to `α`.
-/
unsafe def TypeName.mk (α : Type u) (typeName : Name) : TypeName α :=
⟨unsafeCast typeName⟩
private unsafe def TypeName.typeNameImpl (α) [TypeName α] : Name :=
unsafeCast (@TypeName.data α _)
/--
Returns a declaration name of the type.
-/
@[implemented_by TypeName.typeNameImpl]
opaque TypeName.typeName (α) [TypeName α] : Name
private opaque DynamicPointed : NonemptyType.{0} :=
⟨Name × NonScalar, inferInstance⟩
/--
Type-tagged union that can store any type with a `TypeName` instance.
This is roughly equivalent to `(α : Type) × TypeName α × α` but without the
universe bump.
-/
def Dynamic : Type := DynamicPointed.type
instance : Nonempty Dynamic := DynamicPointed.property
private unsafe def Dynamic.typeNameImpl (any : Dynamic) : Name :=
(unsafeCast any : Name × NonScalar).1
/--
The name of the type of the value stored in the `Dynamic`.
-/
@[implemented_by Dynamic.typeNameImpl]
opaque Dynamic.typeName (any : Dynamic) : Name
private unsafe def Dynamic.get?Impl (α) (any : Dynamic) [TypeName α] : Option α :=
let ((typeName, obj) : Name × NonScalar) := unsafeCast any
if typeName == TypeName.typeName α then
some (unsafeCast obj)
else
none
/--
Retrieves the value stored in the `Dynamic`.
Returns `some a` if the value has the right type, and `none` otherwise.
-/
@[implemented_by Dynamic.get?Impl]
opaque Dynamic.get? (α) (any : Dynamic) [TypeName α] : Option α
private unsafe def Dynamic.mkImpl [TypeName α] (obj : α) : Dynamic :=
unsafeCast (TypeName.typeName α, (unsafeCast obj : NonScalar))
@[implemented_by Dynamic.mkImpl]
opaque Dynamic.mk [TypeName α] (obj : α) : Dynamic