1 import Base 2 # Generic heterogeneous owner product, not a registry metadata adapter. 3 # Library-generated paths retain the physical type through arbitrary nesting. 4 type Owner<-L:Type,-R:Type> is Type: 5 Owner{left:L,right:R} 6 type Path is Data: 7 Left{} 8 Right{} 9 def Part(~L:Type,~R:Type,path:Path) -> Type: 10 match path: 11 case Left{}:L 12 case Right{}:R 13 def Rest(~L:Type,~R:Type,path:Path) -> Type: 14 match path: 15 case Left{}:R 16 case Right{}:L 17 def take(~L:Type,~R:Type,path:Path,owner:Owner) -> Rest(~L,~R,path) & Part(~L,~R,path): 18 match path owner: 19 case Left{} Owner{left,right}:(right,left) 20 case Right{} Owner{left,right}:(left,right) 21 def put(~L:Type,~R:Type,path:Path,rest:Rest(~L,~R,path),part:Part(~L,~R,path)) -> Owner: 22 match path: 23 case Left{}:Owner{part,rest} 24 case Right{}:Owner{rest,part} 25 # Canonical setup composes these fields; user systems only receive opaque caps. 26 type Lens<-Whole:Type,-Part:Type,-Rest:Type> is Type: 27 Lens{take:Whole -> Rest & Part,put:Rest -> Part -> Whole} 28 def lens(~L:Type,~R:Type,~path:Path) -> Lens,Part(~L,~R,path),Rest(~L,~R,path)>: 29 Lens{owner=>take(~L,~R,path,owner),rest=>part=>put(~L,~R,path,rest,part)} 30 def get_field(~W:Type,~P:Type,~R:Type,value:Lens) -> W -> R & P: 31 match value: 32 case Lens{get,_}:get 33 def put_field(~W:Type,~P:Type,~R:Type,value:Lens) -> R -> P -> W: 34 match value: 35 case Lens{_,put}:put 36 def joined(~A:Type,~B:Type,~P:Type,outer:A,observed:B & P) -> (A & B) & P: 37 match observed: 38 case (inner,part):((outer,inner),part) 39 def inward(~W:Type,~M:Type,~A:Type,~P:Type,~B:Type,~inner:Lens,observed:A & M) -> (A & B) & P: 40 match observed: 41 case (rest,middle):joined(~A,~B,~P,rest,get_field(~M,~P,~B,inner)(middle)) 42 def composed_take(~W:Type,~M:Type,~A:Type,~P:Type,~B:Type,~outer:Lens,~inner:Lens,owner:W) -> (A & B) & P: 43 inward(~W,~M,~A,~P,~B,~inner,get_field(~W,~M,~A,outer)(owner)) 44 def composed_put(~W:Type,~M:Type,~A:Type,~P:Type,~B:Type,~outer:Lens,~inner:Lens,rest:A & B,part:P) -> W: 45 match rest: 46 case (outerRest,innerRest):put_field(~W,~M,~A,outer)(outerRest,put_field(~M,~P,~B,inner)(innerRest,part)) 47 def compose(~W:Type,~M:Type,~A:Type,~P:Type,~B:Type,~outer:Lens,~inner:Lens) -> Lens: 48 Lens{owner=>composed_take(~W,~M,~A,~P,~B,~outer,~inner,owner),rest=>part=>composed_put(~W,~M,~A,~P,~B,~outer,~inner,rest,part)}