<div dir="auto">musing on this</div><div dir="auto"><div><a href="https://mail.haskell.org/pipermail/beginners/2018-October/018363.html">https://mail.haskell.org/pipermail/beginners/2018-October/018363.html</a></div><br></div><div dir="auto">to which my reply talked mainly about Trex.</div><div dir="auto"><br></div><div dir="auto">Does it make sense to regard a Trex record (or any free-standing anonymous/extensible record) as a container, with values 'lifted' into the structure, and an interface given by the label names, _not_ by order of fields? That is, "container" in the Monad sense?</div><div dir="auto"><br></div><div dir="auto">Does it further make sense if all the values are already lifted into some Functor (like Maybe or (Either e) ) to hoist the Functor out over the record structure?</div><div dir="auto"><br></div><div dir="auto">I'm not sure I'm up with the program for Functor/Applicative/Monad everywhere. If a record structure is a Functor, what's the type constructor? `Rec`? If record structure is an Applicative, what's the constructor for `pure` that lifts into `Rec`? The `<*>` aka `ap` or bind for a Monad presumably is to take two records (with disjoint labels) and concatenate them to a single record.</div><div dir="auto"><br></div><div dir="auto">Given</div><div dir="auto"><br></div><div dir="auto">data Person = Person (Rec( name :: String, age :: Int))</div><div dir="auto"><br></div><div dir="auto">we want, corresponding to the question:</div><div dir="auto"><br></div><div dir="auto">Person <?$>  (age = 27) <*> (name = "Joe")</div><div dir="auto"><br></div><div dir="auto">in which operator <?$> is map-like: it takes a function to its left that expects a record of n fields, then maps over n singleton records with corresponding labels appearing in any order.</div><div dir="auto"><br></div><div dir="auto">I might be able to get there by generics/reflection over the field names embedded in data constructor `Person`s type, then overloading <?$> to look for each label. That is, if Hugs had any sort of generics/TypeRep.</div><div dir="auto"><br></div><div dir="auto">Label names in Trex are literals; there's no such thing as a label variable. (Which is why it's a tad annoying that they start lower case.) Furthermore the same label name must appear in both terms and types -- in fact labels occupy a namespace separate vs terms or types. So Trex is a long way from from generic record handling like:</div><div dir="auto"><br></div><div dir="auto">recAppend :: ( rho'\__x ) => Rec rho' -> Rec ( __x :: a) -> Rec ( __x :: a | rho')</div><div dir="auto">recAppend rho ( __x = x ) = ( __x = x | rho )</div><div dir="auto"><br></div><div dir="auto">in which I've used double-underscore prefix to signify a label variable. This is intended to extend a record `rho` with a singleton record. If we try appending a record with more than one field, beware that field order is arbitrary, so this</div><div dir="auto"><br></div><div dir="auto">recAppend rho ( __x = x, __y = y) = ...</div><div dir="auto"><br></div><div dir="auto">has no principal type (a familiar difficulty). The programmer doesn't care which way round labels `__x, __y` bind, providing they're distinct, but the typing does care.</div><div dir="auto"><br></div><div dir="auto">Some sort of generic record extend/concatenate would be great. You might, looking at Trex syntax, think that `|` is it. This is valid:</div><div dir="auto"><br></div><div dir="auto">( x = "x" | (y = 'y' | (z = 3.14)))</div><div dir="auto">( x = "x", y = 'y', z = 3.14 )           -- equivalent</div><div dir="auto"><br></div><div dir="auto">I could put any record value in place of `(z = 3.14)`. But not in place of the `x = ..` or `y = ...`: `|` is not an operator, not commutative, not associative. Furthermore this is a place where parentheses make a difference, unlike usually in Haskell. So the following are not equivalent, indeed they're all invalid syntax</div><div dir="auto"><br></div><div dir="auto">( (x = "x") | (y = 'y' | (z = 3.14)))       -- x = ... has parens</div><div dir="auto">( x = "x"  | (y = 'y' | z = 3.14 ))          -- z = ... doesn't have parens</div><div dir="auto">( x = "x" | y = 'y' | (z = 3.14) )           -- z = ... in parens OK, but y = ... is not</div><div dir="auto">( (x = "x") | (y = 'y') | (z = 3.14) )      -- no chance<br></div><div dir="auto"><br></div><div dir="auto">I'd like to write term `( rho1 | rho2 )` to concatenate two records. That's currently unrecognised syntax, so I think could be added as such. What would be its type/is it principal?</div><div dir="auto"><br></div><div dir="auto">( rho1 | rho2 ) :: (rho1' \\ rho2') => Rec( rho1' | rho2' )    -- inventing more syntax</div><div dir="auto"><br></div><div dir="auto">in which constraint `(rho1' \\ rho2')` requires the two rows' labels be mutually disjoint -- read "lacks all". Ur/web has something like this. Note I'm not envisaging `|` as a genuine operator: this is still hard-wired syntax; pipe is a reserved symbol in H98 anyway.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">AntC</div>