Я сомневаюсь, что в Haskell есть решение, но в языках есть довольно простое определение с зависимыми парами и типами равенства. Я работаю в Идрисе ниже.
Во-первых, мы говорим, что два элемента в f
функторе имеют одинаковую форму, если они становятся равными после заполнения ()
:
SameShape : Functor f => f a -> f b -> Type
SameShape fa fb = (map (const ()) fa = map (const ()) fb)
Элементы Arg f a
являются элементами f a
, так что нет элементов f Void
с одинаковой формой.
Arg : (f : Type -> Type) -> Functor f => Type -> Type
Arg f a = (fa : f a ** ((fv : f Void) -> SameShape fa fv -> Void))
**
обозначает зависимую пару, где компонент справа может ссылаться на первый компонент. Это определение исключает именно те значения, которые не содержат a
. Итак, мы имеем желаемое свойство:
lem : Functor f => Arg f Void -> Void
lem (fv ** p) = p fv Refl
, где Refl
доказывает map (const ()) fv = map (const ()) fv
.
Это не работает для IO
, но я не думаю, что для этого есть какое-то разумное определение.