| | 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 | |