| 31 | === Basic data types === |

| 32 | |

| 33 | In the generated code, we need closures, array families, array closure, and so forth. We define closure as: |

| 34 | {{{ |

| 35 | data a :-> b = forall e. !(e -> a -> b) :$ e |

| 36 | }}} |

| 37 | with basic closure cosntruction and application as |

| 38 | {{{ |

| 39 | lam :: (a -> b) -> (a :-> b) |

| 40 | lam f = const f :$ () |

| 41 | |

| 42 | ($:) :: (a :-> b) -> a -> b |

| 43 | (f :$ e) $: x = f e x |

| 44 | }}} |

| 45 | |

| 46 | Moreover, we have a type class `PA` determining the types of values that may occur as array elements in flattened arrays. The array type family `PArr` is associated with `PA`: |

| 47 | {{{ |

| 48 | class PA a where |

| 49 | data PArr a |

| 50 | replicateP :: Int -> a -> PArr a |

| 51 | mapP :: PA b => (a -> b) -> PArr a -> PArr b |

| 52 | ..and so on.. |

| 53 | }}} |

| 54 | |

| 55 | A crucial element in the transformation is the representation of arrays of closures as ''array closures'': |

| 56 | {{{ |

| 57 | data a :=> b |

| 58 | = forall e. PA e => |

| 59 | !(PArr e -> PArr a -> PArr b) ::$ PArr e |

| 60 | }}} |

| 61 | We apply array closures as follows: |

| 62 | {{{ |

| 63 | ($::) :: (a :=> b) -> PArr a -> PArr b |

| 64 | (fs ::$ es) $:: as = fs es as |

| 65 | }}} |

| 66 | |