{"id":17796369,"url":"https://github.com/d-plaindoux/thicket","last_synced_at":"2025-03-17T02:31:15.667Z","repository":{"id":18469746,"uuid":"21664667","full_name":"d-plaindoux/thicket","owner":"d-plaindoux","description":"Strong typed functional programming language dedicated to backend and web applications","archived":false,"fork":false,"pushed_at":"2017-03-14T20:17:51.000Z","size":1593,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-27T17:35:51.630Z","etag":null,"topics":["functional-programming","javascript","language","strongly-typed"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/d-plaindoux.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-07-09T18:55:11.000Z","updated_at":"2020-12-21T11:28:54.000Z","dependencies_parsed_at":"2022-09-11T17:21:56.740Z","dependency_job_id":null,"html_url":"https://github.com/d-plaindoux/thicket","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-plaindoux%2Fthicket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-plaindoux%2Fthicket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-plaindoux%2Fthicket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d-plaindoux%2Fthicket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/d-plaindoux","download_url":"https://codeload.github.com/d-plaindoux/thicket/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243841211,"owners_count":20356443,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functional-programming","javascript","language","strongly-typed"],"created_at":"2024-10-27T11:45:12.893Z","updated_at":"2025-03-17T02:31:14.908Z","avatar_url":"https://github.com/d-plaindoux.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Thicket\n\n[![Build Status](https://travis-ci.org/d-plaindoux/thicket.svg)](https://travis-ci.org/d-plaindoux/thicket) \n[![Coverage Status](https://coveralls.io/repos/d-plaindoux/thicket/badge.png?branch=master)](https://coveralls.io/r/d-plaindoux/thicket?branch=master) \n[![unstable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges)\n\nThicket is a lazy functional programming language. It has been inspired at the beginning by the Model, Controller and View approach. In this  approach  a model  denotes  a set  of  data  (atomic or  object) federated in  a named  structure. A controller  is a set  of behaviors applied to a  given model or controller and finally a view  denotes an extended DOM fragment used for UI management.\n\nThicket is a  strong typed language based on well known Hindley-Milner type system and type inference paradigm. The Thicket source code \nis compiled and the resulting objcode is executed by an abstract machine derived from Krivines' machine. Such abstract machine can therefore be implemented in various languages like Java, Python etc. \n\n## Online examples\n\n### Hello World\n\nA simple [Hello world](https://github.com/thicket-lang/thicket-examples/blob/master/helloWorld/index.html) \nis available for execution [here](http://d.plaindoux.free.fr/thicket/thicket/examples/helloWorld.html).\n\n### Todo MVC\n\nThe [TodoMVC](https://github.com/thicket-lang/thicket-examples/tree/master/todoMVC) example available \nfor execution [here](http://d.plaindoux.free.fr/thicket/thicket/examples/todoMVC/index.html) shows a complete\nexample based on dom manipulation.\n\n### Thicket Console\n\nThe [Console](https://github.com/thicket-lang/thicket-examples/tree/master/thicket) example available \nfor execution [here](http://d.plaindoux.free.fr/thicket/thicket/examples/thicket/console.html) shows how the \nruntime can be easily extended in order to provide a naive embedded interpret in the web browser.\n\n### Unit testing\n\nThe [Test](https://github.com/thicket-lang/thicket-examples/tree/master/tests) example available \nfor execution [here](http://d.plaindoux.free.fr/thicket/thicket/examples/tests/assertSpecs.html) and \n[here](http://d.plaindoux.free.fr/thicket/thicket/examples/tests/assertSpecs.2.html) shows how\nunit testing can be done just changing the logger used to display the result.\n\n### Additional projects\n\nSome projects are also available in Hyperweb and can be browsed and executed seamlessly. For instance \na [naive \u0026lambda;-calculus evaluation](https://helix-fairy.gomix.me) is available for test.\n\n## Language Overview\n\nThe Thicket language  came from research done about  strong object and\nclass   separation. In addition UI management done using DOM fragment \nis provided in order to define  view   facet  in   addition to object  \n(model)   and  class (controller).\n\n### Model\n\n**keywords:** *data denotation*\n\nFirst information and data are stored in an object. In our approach an\nobject is not  meant to have behaviors but only  provides a common and\nsimple  way  for  data  structuration and  storage.   It's  the  model\ndefinition in the illustrated MVC design pattern.\n\n```\nmodel Person {\n   firstname: string\n   name: string\n   age: number\n}\n```\n\nThen using such model creating an instance can be easily done. In fact a\nmodel defines a generator which is a function named with the model name.\n\n```\n// Person : string -\u003e string -\u003e number -\u003e Person\nPerson \"John\" \"Doe\" 42\n```\n\n### Class\n\n**keywords:** *behavior - control - denotation*\n\nA  class provides  a  set of  behaviors where  the  internal state  is\nrepresented by  a model.  For instance  in the  next code  two classes\n`person`  and  `population`  are  proposed for  objects  `Person`  and\n`list[Person]`. Such class is similar to a controller in charge of managing\na given model.\n\n```\nclass person this:Person {  \n  with Person\n  \n  tick: person\n} {\n  def firstname = this.firstname\n  def name = this.name\n  def age = this.age\n  \n  def tick = person new this with age=(this.age + 1)\n}\n```\nThen using such class creating an instance can be easily done. In fact a\nclass defines a generator which is a function named with the class name.\n\n```\n// person : Person -\u003e person\nperson (Person \"John\" \"Doe\" 42)\n```\n\nIn addition we can define type in order to increase specification readability\nusing typedef capability and reuse this new type definition when defining\nentities.\n\n```\ntypedef Population = list[Person]\n\nclass population this:Population {\n  unbox: Population\n  (\u003c=): number -\u003e population\n  addNew: string -\u003e string -\u003e population\n} {\n  def unbox = this\n  def (\u003c=) age = population for p \u003c- this if p \u003c= 100 yield p\n  def addNew f n = population $ this +: (Person f n 0)\n}\n```\n### View using DOM fragment\n\n**keywords:** *templating, UI fragment*\n\nFinally  views can  be  designed  and linked  to  controllers. In  the\nexample  we   propose  views  dedicated   to  a  `person`  and   to  a\n`population`. These  views define  the UI  using HTML  fragments. This\napproach is  similar to [React](http://facebook.github.io/react/).\n\n```\ndef personView : person -\u003e dom = this -\u003e {\n  \u003cdiv\u003e \n    \u003cdiv\u003ethis.firstname\u003c/div\u003e\n    \u003cdiv\u003ethis.name\u003c/div\u003e\n    \u003cdiv\u003ethis.age\u003c/div\u003e\n  \u003c/div\u003e\n  onMouseEvent MouseClick $ _ -\u003e this.tick\n}\n```\n\nThe main  purpose of views is  the capability to define  a specific UI\n(HTML  fragment) in  a  single and  isolated  block.  Then  identified\nelements become  part of  the definition in  opposite to  anonymous UI\ndefinition.   In  the  next  definition  a  `personAdder`  has  always\nidentified  elements  like  `firstname`  and  `name`.  Based  on  such\ndefinition each `PersonAdder` instance  provides these definitions and\nthen can be referenced as we do in the `Population#addPerson` method.\n\n```\ndef personAdder : population -\u003e dom = this -\u003e {\n    \u003cform\u003e\n        \u003cinput type=\"text\" id=\"firstname\"/\u003e\n        \u003cinput type=\"text\" id=\"name\"/\u003e\n        \u003cinput type=\"submit\" value=\"Add\"/\u003e\n    \u003c/form\u003e\n    onFormEvent OnSubmit $ d -\u003e\n        for firstname \u003c- { d find \"firstname\" }\n            name      \u003c- { d find \"name\"      } \n        yield this addNew firstname name\n}\n\ndef populationView : population -\u003e dom = population -\u003e {\n    \u003cdiv\u003e\n        { for p \u003c- (population \u003c= 100 unbox) yield personView $ person p }\n        { personAdder this }\n    \u003c/div\u003e\n}\n```\n\nSee current [Libraries](https://github.com/thicket-lang) for more language highlights and \n[Examples](https://github.com/thicket-lang/thicket-examples) for small web and backend \napplications.\n\n### Adapters\n\n**keywords:** *substitutability, implicit transformation*\n\nImplicit data adaptation can be done in order to reduce boiler plate \nwhen dealing with objects. For instance when a `string` is required \nthis one can be transparently created from a `number`. \n\n```    \ndef adapter number2string : number -\u003e string = number::toString\n\n// \"a\" + 1 === \"a\" + (number2string 1) === \"a1\"\n```\n\nThese adaptations can be ordered explicitely or inferred by the compiler \nduring the type checking stage. Adapter accessibility is managed using \nimports then if such an adapter is not imported the related transformation \nis not available.\n\nFinally adaptation is not transitive. For this purpose all required transformations \nmust be expressed using dedicated adapters.\n\nThis can be compared to **implicit conversion** mechanism available in \n[Scala](http://docs.scala-lang.org/overviews/core/implicit-classes.html) \nor [C#](https://msdn.microsoft.com/fr-fr/library/xhbhezf4.aspx). \n\n### Derivation\n\n**keywords:** *classification, reusability, subtype*\n\nClass derivation can help reducing specification based on classification. Such \nderivation is the main paradigm used for the subtyping relationship and then the\nsubstitutability principle availability.\n\n```\nmodel Equal[a] { \n    (==) : a -\u003e bool\n)\n\nclass number this:native {\n    with Equal[number]\n} {\n    def (==) = ...\n}\n```\n\nThen each time a `Equal[number]` parameter is required a number can be proposed for \ninstance. This implies the avaibility of the subtyping type relationship implied by \nthe derivation declaration in the language.\n\n### Traits\n\n**keywords:** *abstract behavior denotation, derivable, composition*\n\nA trait is an abstract component providing behaviors without any constraint \nrelated to the denoted data type.\n\n```\nmodel Comparable[a] {\n    (==) : a -\u003e bool\n    (!=) : a -\u003e bool\n    (\u003c=) : a -\u003e bool\n    (=\u003e) : a -\u003e bool\n    (\u003c?) : a -\u003e bool\n    (?\u003e) : a -\u003e bool\n}\n\ntrait comparable[a] {\n    with Comparable[a]\n} {\n    def (!=) n = (self == n) not    \n    def (\u003c=) n = (self == n) || (self \u003c? n)\n    def (=\u003e) n = n \u003c? self\n    def (?\u003e) n = n \u003c= self    \n}\n\nclass bool this:Bool {\n    with comparable[bool]\n    fold : [b] b -\u003e b -\u003e b\n} {\n    def True.fold t _ = t\n    def False.fold _ f = f\n    \n    def (==) b = self fold b b.not    \n    def (\u003c?) b = self fold false (b fold false true)\n}\n```\n\n### Private behaviors\n\n**keywords:** *privacy, behavior protection*\n\nA trait or a class can be defined with provite behaviors. Such definitions\nare then only available when using 'self'. A private behavior is defined with \na type in the definition section. \n\n```\ntrait page {\n    create : dom -\u003e dom\n} {\n    def header : dom = \u003cdiv class=\"header\"\u003e \"...\" \u003c/div\u003e\n    def footer : dom = \u003cdiv class=\"footer\"\u003e \"...\" \u003c/div\u003e\n    def create d = \u003cbody\u003e self.header d self.footer \u003c/body\u003e\n}\n```\n\n### String interpolation\n\n**keywords:** *string format, injected expression*\n\nString interpolation unleashes string construction allowing string embedded code.\n\n```\nmodel Message {\n    id   : number\n    text : string \n}\n\ndef logMessage : Message -\u003e console = m -\u003e \n    console.log $\"${date current}::${m id} - ${m text}\" \n```\n\n### System Evolution\n\n**keywords:** *immutablity, data evolution/mutation*\n\nSince immutability is an important paradgim in the language data mutability is based on \nobject evolution rather than object modification using side effects. For this purpose\na dedicated instruction is proposed. The result of such instruction is a new data built \nusing an original and a set of modified attributes or methods. A data can be simple model\ninstance but also a class instance. This last perspective allows code mutation.\n\n#### Model Evolution\n\nIn the following example the address is defined in the `Person` model. Then changing address \ncan be done but at the model level.\n\n```\nmodel Person {\n   name : string\n   address : string\n}\n\ndef changeAddress : string -\u003e Person -\u003e Person = s p -\u003e {\n   new p with address=s\n}\n```\n\n#### Class Evolution\n\nIn the following example the address is defined in the class instead in the `Person` model. \nThen changing address can be done but at the class level.\n\n```\nmodel Person {\n   name : string\n}\n\nclass localizedPerson this:Person {\n   with Person\n   address : option[string]\n   changeAddress : string -\u003e localizedPerson\n} {\n   def name = this name\n   def address = none\n   def changeAddress s = new self with address=(some s)\n}\n```\n\n## Not yet in the language\n\n### Type of self in traits\n\nSince traits defines partial definitions allowing self usage the related type is only\nknown when such trait is used in a class.\n\n```\ntrait Set[M,a] {\n    empty  : bool\n    size   : number\n    // Etc.    \n} {\n    def empty = self size == 0\n}\n```\n\nIn this example `self` has the behavior `size` because *it's an \nimplementation* of a `Set`. But what does *implementation* means in the \ntype system. In fact the self type is a type containing `Set` \nspecification i.e. a class with a derivation to this trait. \n\nFor the moment the type of self is the trait type itself but this approach \nis not fulfiling. \n\n## TODO\n\n### Type checker level\n\n#### Consistency\n\nFor each class definition check the consistency in order to reject \npartial class definition since a class cannot abstract. Not used as-is \nin another one using the `with` declaration.\n\n### Code generation level\n\n#### Generated code optimization\n\nThe current version of the generated code refers to the module in two\nmany levels (module entity, model, class ... and ident). This repetition\nmust be build when specifications are loaded (synthetized).\n\n#### Constant pool\n\nEach constant like strings, number etc. must be stored in a constant pool\nlike in the class representation for the `JVM`. This implies a more compact \nspecification file.\n\n## More informations and References\n\nThis language has been inspired  by major projects and frameworks like\n[Purescript](https://github.com/purescript/purescript) and\n[React](http://facebook.github.io/react/). In addition the Virtual DOM\napproach is also studied in order to provide a reactive and efficient \nDOM management process.\n\n## License\n\nCopyright (C)2015-2016 D. Plaindoux.\n\nThis program is  free software; you can redistribute  it and/or modify\nit  under the  terms  of  the GNU  Lesser  General  Public License  as\npublished by  the Free Software  Foundation; either version 2,  or (at\nyour option) any later version.\n\nThis program  is distributed in the  hope that it will  be useful, but\nWITHOUT   ANY  WARRANTY;   without  even   the  implied   warranty  of\nMERCHANTABILITY  or FITNESS  FOR  A PARTICULAR  PURPOSE.  See the  GNU\nLesser General Public License for more details.\n\nYou  should have  received a  copy of  the GNU  Lesser General  Public\nLicense along with  this program; see the file COPYING.  If not, write\nto the  Free Software Foundation,  675 Mass Ave, Cambridge,  MA 02139,\nUSA.\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd-plaindoux%2Fthicket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fd-plaindoux%2Fthicket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd-plaindoux%2Fthicket/lists"}