Search code examples
idrismonoids

Idris - use same interface instance


I have a data structure

record IdentityPreservingMorphism domain codomain where
constructor MkMorphismOfMonoids
  func : domain -> codomain
  funcRespId : (Monoid domain, Monoid codomain) => func (Algebra.neutral) = Algebra.neutral

which just says that an IdentityPreservingMorphism is a morphism between monoids which needs to respect the identity.

I'm trying to prove that the identity morphisms is an IdentityPreservingMorphism

monoidIdentity : Monoid m => MorphismOfMonoids m m
monoidIdentity = MkMorphismOfMonoids
  id
  ?respId

The easy shot for ?respId at Refl does not work because there are too many Monoid instances available. How can I tell the compiler that I would like to use only the instance coming from the monoidIdentity definition?


Solution

  • The "proper" solution to this requires (1) writing a proof of a form (m1 : Monoid m, m2 : Monoid m) => m1 = m2 and 2) being able to reify the two Monoid implementations from funcRespId to feed them into step 1. While the former can be simulated with a postulate/assert, it's the latter step that becomes problematic, which is probably related to https://github.com/idris-lang/Idris-dev/issues/4591.

    A simpler workaround is to trivialize reification by storing implementations directly in the record:

    record MorphismOfMonoids domain codomain where
      constructor MkMorphismOfMonoids
      func : domain -> codomain
      mon1 : Monoid domain
      mon2 : Monoid codomain
      funcRespId : func (Algebra.neutral @{mon1}) = Algebra.neutral @{mon2}
    
    monoidIdentity : Monoid m => MorphismOfMonoids m m
    monoidIdentity @{mon} = MkMorphismOfMonoids id mon mon Refl