В Хаскеле я не могу найти простой способ заставить ваш код работать.
Мне кажется интересным, что ваша идея работает на языке с полностью зависимыми типами, такими как Coq (и, вероятно, Agda, Idris и т. Д.).
Основной смысл, как указывает Даниэль Вагнер, состоит в том, что тип, полученный из f
, может зависеть от значения c
, поэтому пара (c,d)
в исходном коде должна быть зависимой парой .
Для чего это стоит, вот как мы можем сделать это в Coq.
Обратите внимание, что это не относится к необитаемому типу, например forall a. a
.
(* An existential type, under an impredicative encoding *)
Inductive V (A: Type): Type :=
Vk : forall (B: Type), (B -> A) -> V A
.
(* The usual "identity to equivalence" *)
Definition subst {A B: Type} (p: A = B) (x: A): B :=
match p with
| eq_refl => x
end .
(* The main function.
Essentially, we want to turn
Vk B (fun b => Vk C g)
into
Vk (B*C) (fun (b,c) => g c)
but both C and g can depend on (b:B), so (B*C)
should be a Sigma type {b:B & ty b}.
*)
Definition down (A: Type) (x: V (V A)): V A :=
match x with
| Vk B f => let
ty (z: V A): Type := match z with | Vk C g => C end
in Vk A {b:B & ty (f b)} (fun w =>
match w with
| existT b y =>
match f b as o return ty (f b) = ty o-> A with
| Vk C g => fun (h: ty (f b) = C) =>
g (subst h y)
end eq_refl
end )
end .