Let’s have an example of non-regular mutually recursive data types, for example

```
type 'a s = SS of 'a
and t = int s
and u = float s
```

And we want to create transformation functions for these three types. The transformation functions of two sorts: showing stuff

```
val show_s : ('a -> string) -> 'a s -> string
val show_t : t -> string
val show_u : u -> string
```

and mapping stuff (I actually want `fmap`

s but I shrinked typed here for simplicity)

```
val map_s : ('a -> 'a) -> 'a s -> 'a s
val map_t : t -> t
val map_u : u -> u
```

And I want to write *separate* function for each type and tie these three functions to the knot using another function (I call it `fix`

). I want this `fix`

function to be the same for showing and fmaping. A already have the `fix`

functions per transformation kind which have the same body but have different types.

Let me show that naive approach fails. These are the initial transformation for showing

```
let show0_s fa _s _t _u (SS a) = fa a
let show0_t s _t _u = s (sprintf "%d") s _t _u
let show0_u s _t _u = s (sprintf "%f") s _t _u
```

Let’s try to tie the knot

```
let fix1 (s0,t0,u0) =
let rec s = fun fa -> s0 fa s0 t u
and t = fun what -> t0 s0 t u what
and u what = u0 s0 t u what
in
(s,t,u)
let (show_s,show_t,show_u) = fix1 (show0_s, show0_t, show0_u)
^^^^^^^
```

Blah, blah, `Type float is not compatible with type int`

Let’s workaround this issue by introducing existential quantification. It works for `show`

ish functions. We start from initial implementations which abuse existential quantification

```
type init2s =
{ s_init2: 'a . ('a -> string) ->
init2s -> init2t -> init2u ->
'a s -> string }
and init2t =
{ t_init2: init2s -> init2t -> init2u -> t -> string }
and init2u =
{ u_init2: init2s -> init2t -> init2u -> u -> string }
let show2_s = { s_init2 = (fun fa _s _t _u (SS a) -> fa a) }
let show2_t = { t_init2 = (fun s t u -> s.s_init2 (sprintf "%d") s t u) }
let show2_u = { u_init2 = (fun s t u -> s.s_init2 (sprintf "%f") s t u) }
```

```
type 's wrap1s = { s_trf1: 'a . ('a -> 's) -> 'a s -> 's }
type 's wrap1t = { t_trf1: t -> 's }
type 's wrap1u = { u_trf1: u -> 's }
let fix2 (s0,t0,u0) =
let rec s = { s_trf1 = fun fa subj -> s0.s_init2 fa s0 t0 u0 subj }
and t = { t_trf1 = fun subj -> t0.t_init2 s0 t0 u0 subj }
and u = { u_trf1 = fun subj -> u0.u_init2 s0 t0 u0 subj }
in
(s,t,u)
let () =
let s,t,u = fix2 (show2_s,show2_t,show2_u) in
let () = printf "%s\n%!" @@ s.s_trf1 (sprintf "%S") (SS "asdf") in
let () = printf "%s\n%!" @@ s.s_trf1 (sprintf "%b") (SS true) in
let () = printf "%s\n%!" @@ t.t_trf1 (SS 42) in
let () = printf "%s\n%!" @@ u.u_trf1 (SS 3.1415) in
()
```

The problem is that approach doesn’t scale for `fmap`

-like function. In the example above the result type is `string`

with existenatial variable `'a`

but for `fmap`

we need the result type to be parametrized by this existential `'a`

. And hence, if `fix`

function is polymorphic by the type of functions’ results, the `'result`

type should be parametrizable by existential variable. I tried to use library Higher but the locally introduced type escapes the scope. The wrong piece of codeis below, but I doubt it will be helpful

```
open Higher
type ('syns,'syna,'synt,'synu) init3s =
{ s_init3: 'a . ('a -> ('a,'syna) app) ->
('syns,'syna,'synt,'synu) init3s ->
('syns,'syna,'synt,'synu) init3t ->
('syns,'syna,'synt,'synu) init3u ->
'a s -> ('a,'syns) app }
and ('syns,'syna,'synt,'synu) init3t =
{ t_init3: 'syn .
('syns,'syna,'synt,'synu) init3s ->
('syns,'syna,'synt,'synu) init3t ->
('syns,'syna,'synt,'synu) init3u ->
t -> 'syn }
and ('syns,'syna,'synt,'synu) init3u =
{ u_init3: 'syn .
('syns,'syna,'synt,'synu) init3s ->
('syns,'syna,'synt,'synu) init3t ->
('syns,'syna,'synt,'synu) init3u ->
u -> 'synu }
let show3_s = { s_init3 = (fun fa _s _t _u (SS a) -> fa a) }
let show3_t = { t_init3 = (fun s t u ->
let module HS = Higher.Newtype1(struct type 'a t = 'a s end) in
let module HA = Higher.Newtype1(struct type 'a t = string end) in
HS.inj @@ s.s_init3 (fun n -> HA.inj @@ sprintf "%d" n ) s t u)
(* HA.t escapes its scope ^^^^^ *)
}
let show3_u = { u_init3 = (fun s t u -> s.s_init3 (sprintf "%f") s t u) }
```

I can’t make the code with Higher work. I thought about passing the first class module out together with the result of transformation but it seems extremely scary. I basically out of ideas. Do you know any other dirty hacks to work around higher kinded types which have appeared because of existentials? Maybe I can throw away existentials to hack non-regularity in some other manner?