1Branded Values 2============== 3A branded value is an "API value" that carries around its name (called a brand) 4and its documentation as metadata. Functions, modules, and data constructors 5can be branded. These are the components from which library APIs are built. 6 7This is a feature that's found in a less general form in many dynamically 8typed programming languages. It's common for functions and modules 9to carry their name and a docstring as metadata. 10 11Statically typed languages use a mixture of 'structural' and 'nominal' 12equivalence rules for determining type equivalence. In Curv, types are 13values, and Curv has a more general notion of "value equivalence". 14Branded values are compared for equivalence by comparing their brands, 15which means they use nominal equivalence. Unbranded values are compared 16using structural equivalence. 17 18Curv provides a uniform mechanism for defining branded values, and for 19abstracting over them. 20 * In the simplest case, a branded definition 'def B = <function or module>' 21 defines a branded value whose brand is the identifier "B" 22 (and binds it to B in the local environment). 23 * If a branded module "M" has a branded member "f", 24 then f's value has the brand "M.f". 25 * A branded "constructor function" returns a branded value, 26 whose brand (a "call brand") has the form of a function call: 27 the function's brand, followed by the argument values. 28 * There are expressions for constructing anonymous functions, constructor 29 functions, and modules. These anonymous (unbranded) values can then be 30 given a brand. You can also rebrand an already branded value. 31 32A brand is effectively a constructor expression: it's an expression that 33when evaluated in the appropriate environment, reconstructs the original value. 34 35A branded value is printed as its brand. You can use the brand as a pattern 36to match a branded value and bind argument values in a call brand. 37This is a form of data abstraction: the representation of the value is 38hidden behind the expression used to construct the value. 39 40Shapes will become branded values (using the Algebraic Data Abstraction 41feature). All of the standard shape constructors and shape operators 42will become branded data constructors. The brand of a Shape will be a 43tree of operations, like an OpenSCAD CSG tree. The ability to introspect 44this operation tree will have multiple applications. 45 46Branded Values 47-------------- 48A branded value has a brand, which has the form of a constructor 49expression. When evaluated in an appropriate environment, the brand 50reconstructs the original value. Branded values are printed as their brands. 51Equality depends on the brand (two brands can't be equal unless their brands 52are equal). Brands are used for pattern matching. 53 54A brand is: 55 <brand> ::= <identifier> -- name brand 56 | <brand> <argvalue> -- call brand 57 | <brand> . <identifier> -- field brand 58 59Two ontologies of branded values: need to align this with Data Type theory. 60* A branded value is an atom, a function, or a module. 61 An atom is much like a symbol, in that the brand constitutes the entire 62 identity of the value. 63* A branded value is a function, module or data constructor. 64 65A branded value abstractly consists of a brand and a payload. 66The payload for an atom is the unit value. Otherwise the payload is an 67anonymous function or module. 68 69Referential transparency. The mechanisms for constructing branded values 70do not violate referential transparency. 71 72There is an equivalence relation, x === y. 73In general x===y means substitutional equivalence: that x can be substituted 74for y in any context without changing the meaning of the program. For branded 75values, x===y is true if the brand and the payload are equivalent. For POD data, 76equivalence is equality, except that 0 and -0 are not equivalent. For functions, 77equivalence means same parse tree, and nonlocal bindings are equivalent. 78 79Modules and records are distinct. Only modules can be branded. 80* A module is a set of mutually recursive definitions. Dependencies between 81 definitions are preserved in the value, which is relevant when a module is 82 printed or rebranded. Editing a module member would entail editing the 83 source code then re-evaluating it and any dependent members. 84 Module members may be branded. Module equivalence is code equivalence (like 85 functions): same parse tree, equivalent nonlocal bindings. 86* A record is a map from symbols to values. An individual record field can be 87 updated without affecting other fields. 88 89Syntax 90------ 91As a simplification, I'll say that the unit value is `{}`. 92This unifies atoms with modules, reducing the amount of primitive syntax. 93 94A branded definition is: 95 def <id> = <bexpr> 96where <bexpr> computes a module or function. This can be preceeded by a 97docstring, which becomes part of the metadata of a branded value. 98This is legal anywhere a definition is legal, including a let phrase 99and a REPL command. 100 101A *.curv source file in a directory module yields a branded definition 102if the contents of the source file are: 103 <explicit-bexpr> 104optionally preceded by a docstring. An explicit-bexpr is 105 branded <bexpr> 106The 'branded' keyword can be omitted if <bexpr> is a function literal 107or a non-empty module literal. 108 109An anonymous module literal is what used to be called a scoped record literal. 110It may contain branded definitions. Any definition can be preceded by a 111docstring. 112 113An anonymous constructor function is constructed using 114 <param> -> <explict-bexpr> 115There is no docstring before <explicit-bexpr> in this case. 116Calling an anonymous constructor function is the same as calling a regular 117function. The behaviour is different when you print the function, and when 118you bind it using a branded definition. 119 120A general requirement is that you can construct anonymous modules and 121anonymous constructor functions using combinators, then bind them 122using branded definitions. 123 124Implementation 125-------------- 126It is more efficient to construct a function or module with a brand 127than it is to rebrand an existing anonymous function or module. So we 128try to use the former strategy when possible. 129* eval_branded() takes a brand argument. It defaults to calling eval(), then 130 rebranding the result. It is overridden by Function_Expr, Module_Expr 131 and Call_Expr, which use the brand to construct a function or module value. 132 133A Brand contains a helpstring and a label. 134A Label is 135 def Label = { 136 data T = name Symbol | call Function (List Value) | dot T Symbol 137 } 138 factorial = match [ 139 0 -> 1, 140 n -> n * factorial (n - 1) 141 ] 142