Skip to content

Use layered (staged) applicative composition at derivation to improve generation #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
buzden opened this issue Sep 8, 2023 · 0 comments
Labels
code: enhancement New feature or improvement code: redesign New design of some part of the library derive: core Something in between single type generator and its constructors derive: least-effort Relates to the `LeastEffort` derivation algorithm issue: distribution When distribution of generation is wrong issue: performance When work takes too much resources part: derivation Related to automated derivation of generators status: discussion Suggested or reported thing is not obvious to be good enough status: feature request Request for new functionality or improvement

Comments

@buzden
Copy link
Owner

buzden commented Sep 8, 2023

Monadic composition may be ineffective or make distribution bad is there a raw generator lies around. Thus, we can use applicative composition as much as we can in order to generate first values that we can.

Thus, at each moment inside generation we can see which values can be generated (i.e., which values do not depend on any other value which needs to be generated) and generate them in a single pass by composing appropriate generators applicatively. Then we can have the second round, because at this stage of generation some of values can be considered independent, because all values they depend on, are already present. And so on.

This should, by the way, reduce count of possible "orderings" (when calling for a particular data type constructor) which we suffer from currently.

My examples from thinking about this in May '23:

import Test.DepTyCheck.Gen

data X : Type

data Y : Type

data F : Type

fun : Y -> F

data Z : Type

data B : X -> F -> Type

data C : X -> Type

data D : Y -> Type

data D' : Y -> Type

data E : X -> Z -> Type

data T : Type where
  MkA : (x : X) -> (y : Y) -> (z : Z) -> B x (fun y) -> C x -> D y -> D' y -> E x z -> T

genB_f : (f : F) -> Gen (x ** B x f)
genB_xf : (x : X) -> (f : F) -> Gen (B x f)

genC : Gen (x ** C x)
genC_x : (x : _) -> Gen (C x)

genD : Gen (y ** D y)
genD_y : (y : _) -> Gen (D y)

genD' : Gen (y ** D' y)
genD'_y : (y : _) -> Gen (D' y)

genE : Gen (x ** z ** E x z)
genE_x : (x : _) -> Gen (z ** E x z)

genT : Gen T
genT = oneOf

  [ -- (E + D) * (D' + B + C)
    do ((x ** z ** e), (y ** d)) <- (,) <$> genE <*> genD
       (d', b, c) <- (,,) <$> genD'_y y <*> genB_xf x (fun y) <*> genC_x x
       pure $ MkA x y z b c d d' e

  , -- D * (D' + B * (C + E))
    do (y ** d) <- genD
       let l = genD'_y y
       let r : Gen (x ** (B x (fun y), C x, (z ** E x z))) := do
         (x ** b) <- genB_f (fun y)
         (c, (z ** e)) <- (,) <$> genC_x x <*> genE_x x
         pure (x ** (b, c, (z ** e)))
       (d', (x ** (b, c, (z ** e)))) <- (,) <$> l <*> r
       pure $ MkA x y z b c d d' e

  , -- (C + D) * (B + D' + E)
    do ((x ** c), (y ** d)) <- (,) <$> genC <*> genD
       (b, d', (z ** e)) <- (,,) <$> genB_xf x (fun y) <*> genD'_y y <*> genE_x x
       pure $ MkA x y z b c d d' e

  -- ... and other orders, say, D * (D' + C * (B + E)), (E + D') * (D + B + C)
  ]

This suspiciously resembles Arrows composition, thus we may think (again) on 1) automation of arrows computation 2) representing generators as arrows.

@buzden buzden added code: enhancement New feature or improvement status: discussion Suggested or reported thing is not obvious to be good enough part: derivation Related to automated derivation of generators status: feature request Request for new functionality or improvement code: redesign New design of some part of the library issue: performance When work takes too much resources issue: distribution When distribution of generation is wrong derive: least-effort Relates to the `LeastEffort` derivation algorithm derive: core Something in between single type generator and its constructors labels Sep 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
code: enhancement New feature or improvement code: redesign New design of some part of the library derive: core Something in between single type generator and its constructors derive: least-effort Relates to the `LeastEffort` derivation algorithm issue: distribution When distribution of generation is wrong issue: performance When work takes too much resources part: derivation Related to automated derivation of generators status: discussion Suggested or reported thing is not obvious to be good enough status: feature request Request for new functionality or improvement
Projects
None yet
Development

No branches or pull requests

1 participant