{"id":18051490,"url":"https://github.com/jin/subtyping","last_synced_at":"2025-08-27T02:07:20.950Z","repository":{"id":139301850,"uuid":"88614082","full_name":"jin/subtyping","owner":"jin","description":"An implementation of structural subtyping of records and functions","archived":false,"fork":false,"pushed_at":"2018-07-14T17:58:58.000Z","size":24,"stargazers_count":13,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-10T18:02:59.048Z","etag":null,"topics":["haskell","subtypes","subtyping","typechecker"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-04-18T10:47:32.000Z","updated_at":"2022-07-26T22:16:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"fc294c94-c555-4b45-a1af-e33487412afa","html_url":"https://github.com/jin/subtyping","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jin/subtyping","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jin%2Fsubtyping","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jin%2Fsubtyping/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jin%2Fsubtyping/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jin%2Fsubtyping/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jin","download_url":"https://codeload.github.com/jin/subtyping/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jin%2Fsubtyping/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272279497,"owners_count":24905908,"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","status":"online","status_checked_at":"2025-08-27T02:00:09.397Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["haskell","subtypes","subtyping","typechecker"],"created_at":"2024-10-30T22:49:03.824Z","updated_at":"2025-08-27T02:07:20.906Z","avatar_url":"https://github.com/jin.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FunSub: A toy language with structural subtyping\n\nThe purpose of this toy language is to provide a concrete realisation of subtyping concepts.\n\nIt is the accompaniment code of my technical report on Subtyping: [Subtyping: Overview and Implementation](http://jin.crypt.sg/files/subtyping.pdf)\n\nThe typechecker checks well-typedness of subtyping in records (depth, width, permutation) and functions (contravariant in arg, covariant in retval).\n\n### Running\n\nAssuming Haskell is installed and the user is in the project directory, running the following command will invoke the typechecker:\n\n```sh\n$ runhaskell Main.hs examples/typed_expressions.fun\n```\n\nThis produces an output similar to the following:\n\n```\n..\n[Expression]: (fn x :: (Int -\u003e Int) =\u003e 2)\n[Typecheck][OK]: (Int -\u003e Int)\n\n[Expression]: (fn x :: (Int -\u003e Int) =\u003e true)\n[Typecheck][FAIL]: Type mismatch: expected Int, got Bool\n..\n```\n\nThis project can also be built with [Bazel](https://bazel.build) and the [Haskell rules](https://haskell.build)\n\nEnsure that `bazel` and `nix` are installed.\n\n```\n$ bazel build //:subtyping\n$ ./bazel-bin/subtyping  examples/typed_expressions.fun\n```\n\n\n### Architecture\n\nThe components of the language comprises of a REPL/reader, lexer, parser and typechecker. Some examples of FunSub expressions are stored in the `examples/` folder.\n\n`Main.hs` is the entry point that takes in the filename for a file containing `FunSub` expressions. The lexer (`Lexer.hs`) defines reserved tokens and lexemes, and the parser (`Parser.hs`) uses `Parsec` on the tokens to generate an abstract syntax tree (AST) defined in `Syntax.hs`. Lastly, the AST is checked for well-typedness with rules defined in the typechecker (`Typecheck.hs`).\n\n### Example\n\nThe following is a valid expression in the `FunSub` syntax:\n\n```fun\n(fn x :: ({ a: Int, b: Int } -\u003e { a: Int }) =\u003e x)\n  { a = 2, b = 2, c = true } :: { a: Int, b: Int, c: Bool }\n```\n\nIn type systems without subtyping, this function application will not\ntypecheck because the record argument type does not match the parameter type, and the parameter type does not match the function body type even though it is an identity function. However in our subtyping\nimplementation, we are able to use concepts such as *variance* , *width* and *depth* record subtyping to make this expression well-typed.\n\n### Implementation: Typechecker\n\nThe two main functions of the typechecker are `typecheck` and `isSubtype`. Their type signatures are defined as follows:\n\n```hs\n-- Typecheck.hs\nnewtype TypeEnv = TypeEnv (Map String Ty)\n\nisSubtype :: Ty -\u003e Ty -\u003e Bool\ntypecheck :: TypeEnv -\u003e Expr -\u003e Either String Ty\n```\n\n`isSubtype` takes in two types and recursively determines if the first\ntype is a subtype of the second.\n\n`typecheck` takes in a type environment (a mapping of variables to\ntypes) and an AST, and recursively determines if the expression is\nwell-typed. If it is ill-typed, an error message describing the issue is bubbled up and handled in `Main.hs`. If it is well-typed, the exact type is returned to the caller.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjin%2Fsubtyping","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjin%2Fsubtyping","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjin%2Fsubtyping/lists"}