/- Copyright (c) 2014 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Gabriel Ebner -/ prelude import Init.Coe /-! # `NatCast` We introduce the typeclass `NatCast R` for a type `R` with a "canonical homomorphism" `Nat → R`. The typeclass carries the data of the function, but no required axioms. This typeclass was introduced to support a uniform `simp` normal form for such morphisms. Without such a typeclass, we would have specific coercions such as `Int.ofNat`, but also later the generic coercion from `Nat` into any Mathlib semiring (including `Int`), and we would need to use `simp` to move between them. However `simp` lemmas expressed using a non-normal form on the LHS would then not fire. Typically different instances of this class for the same target type `R` are definitionally equal, and so differences in the instance do not block `simp` or `rw`. This logic also applies to `Int` and so we also introduce `IntCast` alongside `Int. ## Note about coercions into arbitrary types: Coercions such as `Nat.cast` that go from a concrete structure such as `Nat` to an arbitrary type `R` should be set up as follows: ```lean instance : CoeTail Nat R where coe := ... instance : CoeHTCT Nat R where coe := ... ``` It needs to be `CoeTail` instead of `Coe` because otherwise type-class inference would loop when constructing the transitive coercion `Nat → Nat → Nat → ...`. Sometimes we also need to declare the `CoeHTCT` instance if we need to shadow another coercion. -/ /-- Type class for the canonical homomorphism `Nat → R`. -/ class NatCast (R : Type u) where /-- The canonical map `Nat → R`. -/ protected natCast : Nat → R instance : NatCast Nat where natCast n := n /-- Canonical homomorphism from `Nat` to a type `R`. It contains just the function, with no axioms. In practice, the target type will likely have a (semi)ring structure, and this homomorphism should be a ring homomorphism. The prototypical example is `Int.ofNat`. This class and `IntCast` exist to allow different libraries with their own types that can be notated as natural numbers to have consistent `simp` normal forms without needing to create coercion simplification sets that are aware of all combinations. Libraries should make it easy to work with `NatCast` where possible. For instance, in Mathlib there will be such a homomorphism (and thus a `NatCast R` instance) whenever `R` is an additive monoid with a `1`. -/ @[coe, reducible, match_pattern] protected def Nat.cast {R : Type u} [NatCast R] : Nat → R := NatCast.natCast -- see the notes about coercions into arbitrary types in the module doc-string instance [NatCast R] : CoeTail Nat R where coe := Nat.cast -- see the notes about coercions into arbitrary types in the module doc-string instance [NatCast R] : CoeHTCT Nat R where coe := Nat.cast