[{"data":1,"prerenderedAt":641},["ShallowReactive",2],{"content-\u002Freference\u002F0.3.x\u002Finformation-contracts":3,"use-cases-nav":634},{"id":4,"title":5,"author":6,"body":7,"date":6,"description":626,"extension":627,"meta":628,"navigation":163,"order":102,"path":629,"seo":630,"stem":631,"version":632,"__hash__":633},"content\u002Freference\u002F0.3.x\u002Finformation-contracts.md","Information Contracts",null,{"type":8,"value":9,"toc":621},"minimark",[10,22,29,35,43,60,74,79,82,234,245,248,321,324,351,358,362,365,457,460,469,504,508,514,517,559,562,601,617],[11,12,13,17,18,21],"p",{},[14,15,16],"em",{},"Finitio"," tries very hard not to be ",[14,19,20],{},"yet another data language",". In\nparticular, it aims at integrating as smoothly as possible with existing\ntechnologies, in particular with programming languages and data exchange\nformats (e.g. JSON or YAML).",[11,23,24,25,28],{},"This interoperability is handled through so-called ",[14,26,27],{},"information contracts",". In\nsome respect, information contracts are the dual of axiomatic contracts, i.e.\nthe dual of public behavioral APIs of software abstractions.",[11,30,31],{},[32,33],"img",{"alt":5,"src":34},"\u002Fimg\u002Fcontracts.png",[11,36,37,38,42],{},"For a given software abstraction, say a ",[39,40,41],"code",{},"Color",":",[44,45,46,54],"ul",{},[47,48,49,50,53],"li",{},"The ",[14,51,52],{},"axiomatic"," contract hides the internal representation in favor of a set\nof public behavioral methods to manipulate the abstraction (e.g. darkening\nand brightening the color),",[47,55,49,56,59],{},[14,57,58],{},"information"," contract hides the internal representation in favor of a\nset of public information representations of the abstraction (e.g. a RGB\ntriple, an hexadecimal string).",[11,61,62,63,66,67,70,71,73],{},"The data types involved in the definitions of the information contracts are\ncalled ",[14,64,65],{},"information types",", e.g. ",[39,68,69],{},"{r: Byte, g: Byte, b: Byte}"," (a tuple type).\n",[14,72,16],{}," provides a rich type system dedicated at capturing those data types\nprecisely, mostly because type systems of mainstream programming languages\nfail at providing good support for them.",[75,76,78],"h2",{"id":77},"dressing-undressing","Dressing & Undressing",[11,80,81],{},"In a more precise way, an information contract is actually a set of\nfunction pairs, such as:",[83,84,89],"pre",{"className":85,"code":86,"language":87,"meta":88,"style":88},"language-finitio shiki shiki-themes github-light github-dark","# RGB information contract\ndress   :: {r: Byte, g:Byte, b: Byte} -> Color\nundress :: Color -> {r: Byte, g:Byte, b: Byte}\n\n# HEX information contract\ndress   :: String( s | s =~ \u002F#[a-f0-9]{6}\u002F ) -> Color\nundress :: Color -> String( s | s =~ \u002F#[a-f0-9]{6}\u002F )\n","finitio","",[39,90,91,100,131,158,165,171,207],{"__ignoreMap":88},[92,93,96],"span",{"class":94,"line":95},"line",1,[92,97,99],{"class":98},"sJ8bj","# RGB information contract\n",[92,101,103,107,111,114,116,119,121,124,128],{"class":94,"line":102},2,[92,104,106],{"class":105},"sVt8B","dress   :: {r: ",[92,108,110],{"class":109},"sj4cs","Byte",[92,112,113],{"class":105},", g:",[92,115,110],{"class":109},[92,117,118],{"class":105},", b: ",[92,120,110],{"class":109},[92,122,123],{"class":105},"} ",[92,125,127],{"class":126},"szBVR","->",[92,129,130],{"class":109}," Color\n",[92,132,134,137,139,142,145,147,149,151,153,155],{"class":94,"line":133},3,[92,135,136],{"class":105},"undress :: ",[92,138,41],{"class":109},[92,140,141],{"class":126}," ->",[92,143,144],{"class":105}," {r: ",[92,146,110],{"class":109},[92,148,113],{"class":105},[92,150,110],{"class":109},[92,152,118],{"class":105},[92,154,110],{"class":109},[92,156,157],{"class":105},"}\n",[92,159,161],{"class":94,"line":160},4,[92,162,164],{"emptyLinePlaceholder":163},true,"\n",[92,166,168],{"class":94,"line":167},5,[92,169,170],{"class":98},"# HEX information contract\n",[92,172,174,177,180,183,187,190,193,196,200,203,205],{"class":94,"line":173},6,[92,175,176],{"class":105},"dress   :: ",[92,178,179],{"class":109},"String",[92,181,182],{"class":105},"( ",[92,184,186],{"class":185},"s4XuR","s",[92,188,189],{"class":126}," |",[92,191,192],{"class":105}," s ",[92,194,195],{"class":126},"=~",[92,197,199],{"class":198},"sA_wV"," \u002F#[a-f0-9]{6}\u002F",[92,201,202],{"class":105}," ) ",[92,204,127],{"class":126},[92,206,130],{"class":109},[92,208,210,212,214,216,219,221,223,225,227,229,231],{"class":94,"line":209},7,[92,211,136],{"class":105},[92,213,41],{"class":109},[92,215,141],{"class":126},[92,217,218],{"class":109}," String",[92,220,182],{"class":105},[92,222,186],{"class":185},[92,224,189],{"class":126},[92,226,192],{"class":105},[92,228,195],{"class":126},[92,230,199],{"class":198},[92,232,233],{"class":105}," )\n",[11,235,236,237,240,241,244],{},"In other words, each public data representation of an abstraction comes\nwith two (pure) functions that allow ",[14,238,239],{},"dressing"," the corresponding\ninformation type with the abstraction behavior, and ",[14,242,243],{},"undressing"," the latter\nthe other way round.",[11,246,247],{},"If information contracts are best explained through abstract data types\nsuch as Color, the dress\u002Fundress principle is more general. It also allows\nexplaining the interoperability of data exchange and programming languages.\nFor instance, the interoperability with JSON could easily be explained as\nfollows:",[83,249,251],{"className":85,"code":250,"language":87,"meta":88,"style":88},"JSNumber = String( s | s =~ ... )\nInteger  = \u003Cjson> JSNumber \\( s | ... ) \\( i | ... )\n",[39,252,253,277],{"__ignoreMap":88},[92,254,255,259,262,264,266,268,270,272,274],{"class":94,"line":95},[92,256,258],{"class":257},"sScJk","JSNumber",[92,260,261],{"class":126}," =",[92,263,218],{"class":109},[92,265,182],{"class":105},[92,267,186],{"class":185},[92,269,189],{"class":126},[92,271,192],{"class":105},[92,273,195],{"class":126},[92,275,276],{"class":105}," ... )\n",[92,278,279,282,285,288,292,295,297,300,302,304,306,309,312,314,317,319],{"class":94,"line":102},[92,280,281],{"class":257},"Integer",[92,283,284],{"class":126},"  =",[92,286,287],{"class":105}," \u003C",[92,289,291],{"class":290},"s9eBZ","json",[92,293,294],{"class":105},"> ",[92,296,258],{"class":109},[92,298,299],{"class":126}," \\",[92,301,182],{"class":105},[92,303,186],{"class":185},[92,305,189],{"class":126},[92,307,308],{"class":105}," ... ) ",[92,310,311],{"class":126},"\\",[92,313,182],{"class":105},[92,315,316],{"class":185},"i",[92,318,189],{"class":126},[92,320,276],{"class":105},[11,322,323],{},"This definition naturally defines the following information contract:",[83,325,327],{"className":85,"code":326,"language":87,"meta":88,"style":88},"dress   :: JSNumber -> Integer\nundress :: Integer -> JSNumber\n",[39,328,329,340],{"__ignoreMap":88},[92,330,331,333,335,337],{"class":94,"line":95},[92,332,176],{"class":105},[92,334,258],{"class":109},[92,336,141],{"class":126},[92,338,339],{"class":109}," Integer\n",[92,341,342,344,346,348],{"class":94,"line":102},[92,343,136],{"class":105},[92,345,281],{"class":109},[92,347,141],{"class":126},[92,349,350],{"class":109}," JSNumber\n",[11,352,353,354,357],{},"The actual parsing\u002Funparsing of JSON from\u002Fto text is generally done by\ndedicated third-party libraries, of course. The example only aims at showing\nthat information contracts are a very general concept, that ",[14,355,356],{},"explains","\nwhat is actually going on in practice.",[75,359,361],{"id":360},"data-interoperability","Data Interoperability",[11,363,364],{},"According to the host programming language, however, the interoperability\nwith exchange formats such as JSON is more of less complete. In Ruby, for\ninstance, the interoperability is already pretty good. It can be explained as\nfollows:",[83,366,368],{"className":85,"code":367,"language":87,"meta":88,"style":88},"RbBoolean = \u003Cjson> JSBoolean\nRbString  = \u003Cjson> JSString\nRbNumeric = \u003Cjson> JSNumber\nRbHash    = \u003Cjson> JSObject\nRbArray   = \u003Cjson> JSArray\n...\n",[39,369,370,386,402,418,435,452],{"__ignoreMap":88},[92,371,372,375,377,379,381,383],{"class":94,"line":95},[92,373,374],{"class":257},"RbBoolean",[92,376,261],{"class":126},[92,378,287],{"class":105},[92,380,291],{"class":290},[92,382,294],{"class":105},[92,384,385],{"class":109},"JSBoolean\n",[92,387,388,391,393,395,397,399],{"class":94,"line":102},[92,389,390],{"class":257},"RbString",[92,392,284],{"class":126},[92,394,287],{"class":105},[92,396,291],{"class":290},[92,398,294],{"class":105},[92,400,401],{"class":109},"JSString\n",[92,403,404,407,409,411,413,415],{"class":94,"line":133},[92,405,406],{"class":257},"RbNumeric",[92,408,261],{"class":126},[92,410,287],{"class":105},[92,412,291],{"class":290},[92,414,294],{"class":105},[92,416,417],{"class":109},"JSNumber\n",[92,419,420,423,426,428,430,432],{"class":94,"line":160},[92,421,422],{"class":257},"RbHash",[92,424,425],{"class":126},"    =",[92,427,287],{"class":105},[92,429,291],{"class":290},[92,431,294],{"class":105},[92,433,434],{"class":109},"JSObject\n",[92,436,437,440,443,445,447,449],{"class":94,"line":167},[92,438,439],{"class":257},"RbArray",[92,441,442],{"class":126},"   =",[92,444,287],{"class":105},[92,446,291],{"class":290},[92,448,294],{"class":105},[92,450,451],{"class":109},"JSArray\n",[92,453,454],{"class":94,"line":173},[92,455,456],{"class":126},"...\n",[11,458,459],{},"Such a mechanism is already built into the Ruby standard library, and explains\nwhy working with JSON data is rather natural in Ruby (because Ruby classes at\nleft above are first-class citizen for Ruby programmers). Among others, this\nallows Finitio-rb to be kept simple, and work with the Ruby type system only,\ndelegating the interoperability with JSON to the usual parsing library. More\nwork might be needed for other programming languages.",[11,461,462,463,465,466,468],{},"Observe, however, that Ruby\u002FJSON interoperability is straightforward but\nactually biased towards JSON. The developer has absolutely no way of stating\nthat some value must be a Ruby ",[39,464,281],{},", since the JSON\nspecification does not distinguish between integers from reals. One aim with\n",[14,467,16],{}," and its type system is to provide a way for developers to fix this,\nby also being able to specify more specific information contracts and have\nfull control of them. In the example, one would like to express an information\ncontract like the following one:",[83,470,472],{"className":85,"code":471,"language":87,"meta":88,"style":88},"RbInteger = \u003Cjson> JSNumber( s | s =~ \u002F^[1-9][0-9]*$\u002F )\n",[39,473,474],{"__ignoreMap":88},[92,475,476,479,481,483,485,487,489,491,493,495,497,499,502],{"class":94,"line":95},[92,477,478],{"class":257},"RbInteger",[92,480,261],{"class":126},[92,482,287],{"class":105},[92,484,291],{"class":290},[92,486,294],{"class":105},[92,488,258],{"class":109},[92,490,182],{"class":105},[92,492,186],{"class":185},[92,494,189],{"class":126},[92,496,192],{"class":105},[92,498,195],{"class":126},[92,500,501],{"class":198}," \u002F^[1-9][0-9]*$\u002F",[92,503,233],{"class":105},[75,505,507],{"id":506},"contracts-in-action","Contracts in Action",[11,509,510,511,513],{},"Dressing and undressing generally applies recursively, e.g. when involving\ncollection and abstract data types. This provides the real ability of\n",[14,512,16],{}," to dress and undress complex data involving many information\ncontracts and many abstractions.",[11,515,516],{},"Consider the following Finitio system, i.e. for dressing sequences of tuples\nhaving a name attribute restricted to simple words:",[83,518,520],{"className":85,"code":519,"language":87,"meta":88,"style":88},"Word = .String( s | s =~ \u002F^[a-z]+$\u002F )\n[{ name: Word }]\n",[39,521,522,549],{"__ignoreMap":88},[92,523,524,527,529,532,534,536,538,540,542,544,547],{"class":94,"line":95},[92,525,526],{"class":257},"Word",[92,528,261],{"class":126},[92,530,531],{"class":105}," .",[92,533,179],{"class":109},[92,535,182],{"class":105},[92,537,186],{"class":185},[92,539,189],{"class":126},[92,541,192],{"class":105},[92,543,195],{"class":126},[92,545,546],{"class":198}," \u002F^[a-z]+$\u002F",[92,548,233],{"class":105},[92,550,551,554,556],{"class":94,"line":102},[92,552,553],{"class":105},"[{ name: ",[92,555,526],{"class":109},[92,557,558],{"class":105}," }]\n",[11,560,561],{},"Dressing JSON data with Finitio-rb, for instance, involves the following contracts:",[44,563,564,574,583,592],{},[47,565,566,567,570,571,573],{},"Dressing ",[39,568,569],{},"JSString"," to Ruby ",[39,572,179],{}," (by the standard library)",[47,575,576,577,579,580,582],{},"Dressing Ruby ",[39,578,179],{}," to ",[39,581,526],{}," (by Finitio-rb, returning a Ruby String)",[47,584,576,585,579,588,591],{},[39,586,587],{},"Hash",[39,589,590],{},"Tuple"," (by Finitio-rb, returning a Ruby Struct)",[47,593,576,594,579,597,600],{},[39,595,596],{},"Array",[39,598,599],{},"Seq"," (by Finitio-rb, returning a Ruby Array)",[11,602,603,604,607,608,610,611,579,614,616],{},"The concrete dressing result is implementation-dependent, as it involves the\ndefinition of the representation function ",[39,605,606],{},"Rep"," that binds Finitio types to\ntypes in the host language. The aim is not to define new host abstractions,\ne.g. classes, for every ",[14,609,16],{}," type defined in a system but rather to check\nthat values ",[14,612,613],{},"conform",[14,615,16],{}," types and choose an idiomatic\nrepresentation in the host language (see the parentheses). However, all those\ninformation contracts are actually involved in the dressing process and\nprovide as many places to validate and coerce data in practice.",[618,619,620],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sA_wV, html code.shiki .sA_wV{--shiki-default:#032F62;--shiki-dark:#DBEDFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":88,"searchDepth":133,"depth":133,"links":622},[623,624,625],{"id":77,"depth":102,"text":78},{"id":360,"depth":102,"text":361},{"id":506,"depth":102,"text":507},"Finitio 0.3.x information contracts: dressing and undressing data.","md",{},"\u002Freference\u002F0.3.x\u002Finformation-contracts",{"title":5,"description":626},"reference\u002F0.3.x\u002Finformation-contracts","0.3.x","0PAlNTVPP-dsiQMj6NbvIN5IzprHge4gJSoQP0wlEOg",[635,638],{"path":636,"title":637},"\u002Fuse-cases","Use cases",{"path":639,"title":640},"\u002Fuse-cases\u002Fcleaning-csv-files","Cleaning .csv files",1786026251329]