{"id":19538072,"url":"https://github.com/dstechenko/fragile","last_synced_at":"2025-09-07T05:34:23.307Z","repository":{"id":180815373,"uuid":"77005110","full_name":"dstechenko/fragile","owner":"dstechenko","description":":rocket: my typelevel experiments","archived":false,"fork":false,"pushed_at":"2017-05-05T23:14:24.000Z","size":123,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-26T04:31:32.317Z","etag":null,"topics":["scala","typelevel"],"latest_commit_sha":null,"homepage":"","language":"Scala","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/dstechenko.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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-21T01:31:59.000Z","updated_at":"2020-10-18T02:37:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"8e2450e3-e73e-46fb-980c-0412fae256a4","html_url":"https://github.com/dstechenko/fragile","commit_stats":null,"previous_names":["dstechenko/fragile"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dstechenko/fragile","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dstechenko%2Ffragile","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dstechenko%2Ffragile/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dstechenko%2Ffragile/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dstechenko%2Ffragile/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dstechenko","download_url":"https://codeload.github.com/dstechenko/fragile/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dstechenko%2Ffragile/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273997334,"owners_count":25204522,"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-09-07T02:00:09.463Z","response_time":67,"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":["scala","typelevel"],"created_at":"2024-11-11T02:31:11.096Z","updated_at":"2025-09-07T05:34:23.256Z","avatar_url":"https://github.com/dstechenko.png","language":"Scala","readme":"# fragile\n\n\u003e The mind is the only weapon that doesn't need a holster. © Paul Blart\n\n**WARNING!** No values were harmed in this module.\n\n## Why?\n\nThis module is designed to investigate and play with Scala type system and it's **Turing completeness**.\n\nAlso to play with **lambda calculus** encodings in types.\n\nThe whole module has no single value used, only types.\n\nScala type system allows encoding of simple building blocks and re-use (in a way) of those to create even more.\nYou could encode natural numbers, build integers on top of those, etc.\nThe same goes for structures like List, Map and even functions.\n\nSome things cannot be done in Scala type system, at least I cannot work out an elegant way to do those.\nThings like abstract over types for type functions, so I have to specialize them manually.\nWe could go and use macros for that, but I decided to keep it simple.\n\nThis module may be helpful for folks who would want to see some weird type level hacking.\nOr who would want to understand what could be done in Scala.\n\nThe name of the module is dedicated to the Scala Compiler.\n\n## Where?\n\nModule is broken down into packages for specific types:\n* [**bool**](src/main/scala/fragile/bool)\n* [**function**](src/main/scala/fragile/function)\n* [**int**](src/main/scala/fragile/int)\n* [**list**](src/main/scala/fragile/list)\n* [**nat**](src/main/scala/fragile/nat)\n* [**product**](src/main/scala/fragile/product)\n\nEach package has a corresponding test laws file.\nTo run laws it is enough to simply compile tests.\n\nPackages have corresponding functions outlined in their package objects.\nAnd also they have **type pattern matching** cases in their regular scala files.\n\nThe idea is to use type matching as little as possible and re-use functions to build new and complex ones.\n\nFor specialized functions next syntax is used:\n* function**N** - [**Nat**](src/main/scala/fragile/nat/Nat.scala)\n* function**B** - [**Bool**](src/main/scala/fragile/bool/Bool.scala)\n* function**I** - [**Int**](src/main/scala/fragile/int/package.scala)\n* function**L** - [**List**](src/main/scala/fragile/list/List.scala)\n\n\n## How much?\n\n### [Bool](src/main/scala/fragile/bool/package.scala)\n\nFunctions implemented:\n* Not\n* Or\n* And\n* If\n\nNotice **De Morgan's laws** usage to reduce **type pattern matching** cases.\n\nAlso, **if** function is specialized manually.\n\n### [Function](src/main/scala/fragile/function/package.scala)\n\nFunctions implemented:\n* Identity\n* Const\n* Manual Eta-expansion\n* AndThen\n* Compose\n* Apply\n\nAll functions work only with [**Nats**](src/main/scala/fragile/nat/Nat.scala).\n\n### [Int](src/main/scala/fragile/int/package.scala)\n\nFunctions implemented:\n* Int\n* Nat\n* Canonical\n* Flip\n* Minus\n* Plus\n* Mult\n\nNotice no need for **type pattern matching** here, as we build on top of [**Nats**](src/main/scala/fragile/nat/Nat.scala).\n\n### [List](src/main/scala/fragile/list/package.scala)\n\nFunctions implemented:\n* List\n* Map\n* FlatMap\n* FoldRight\n* IndexOf\n* :::\n* Reverse\n* SelectSort\n* QuickSort\n* Size\n* TakeLeft\n* ApplyOrElse\n* IsEmpty\n* NonEmpty\n* Count\n* Contains\n* ContainsAll\n* Exists\n* FilterNot\n* Forall\n* SelectSortAsc\n* SelectSortDesc\n* QuickSortAsc\n* QuickSortDesc\n* Corresponds\n* ===\n* IsDefinedAt\n* Distinct\n* IsDistinct\n* RemoveEvery\n* RemoveAll\n* DropLeft\n* DropRight\n* TakeRight\n* StartsWith\n* StartsWithOffset\n* EndsWith\n* Slice\n* Union\n* Diff\n* IndexOfWhere\n* IndexOfWhereFrom\n* IndexOfUntil\n* LastIndexOfUntil\n* LastIndexOf\n* Remove\n* Filter\n* CountWhile\n* TakeWhile\n* DropWhile\n* Partition\n* Tabulate\n* PadTo\n* Intersect\n* FoldLeft\n* ContainsSlice\n* IndexOfSlice\n* IndexOfSliceFrom\n* RemoveSlice\n* LastIndexOfWhere\n* LastIndexOfWhereUntil\n* SegmentLength\n* PrefixLength\n* Updated\n* Sum\n* Product\n\nNotice that all of the **STD Scala List** functions implemented.\n\n### [Nat](src/main/scala/fragile/nat/package.scala)\n\nFunctions implmeneted:\n* Minus\n* Plus\n* Mult\n* Min\n* Max\n* Equal\n* NotEqual\n* Lower\n* Unfold\n* Greater\n* GreaterEqual\n* Lower\n* LowerEqual\n\nNotice handy shorcuts for [**Nats**](src/main/scala/fragile/nat/Nat.scala) in the package object.\n\n### [Product](src/main/scala/fragile/product/package.scala)\n\nFunctions implmeneted:\n* First\n* Second\n* Product\n\nAll functions are specialized manually here.\n\n## How?\n\n### Code blocks\n\nYou may find code organized in blocks. And these blocks follow the same pattern.\n\nThese blocks are used as regular value level code blocks.\n\nEach block has to be manually executed by extracting the last type in the sequence.\n\nThe type is called **run** in these blocks.\n\n``` Scala\ntype computed = ({\n                  type a   = _1\n                  type b   = _1\n                  type run = a + b\n                })#run\n```\n\n### Type pattern matching\n\nEach package has a dedicated scala file with **type pattern matching** cases.\n\nFor instance [**Nat.scala**](src/main/scala/fragile/nat/Nat.scala).\n\nIn these files you may find different type instances with corresponding match cases.\nThe idea is to avoid these cases as much as possible and use functions instead.\nFunctions are defined in corresponding package objects.\n\n``` Scala\n// in Bool\ntype Not \u003c: Bool\n\n// in True\ntype Not = False\n\n// in False\ntype Not = True\n```\n\n### Safe types\n\nScala Compiler is very fragile. Hence the name.\n\nIt cannot resolve cyclic type references, so extra tricks has to be in place for it not to freak out.\n\nBut when you re-use functions in a functional way, you tend to hit those cyclic resolve situations.\n\nTo protect the resolving process you need to re-wrap the calculated type on cyclic type operations.\nBasically tricking the compiler into thinking it is not a cyclic type reference.\n\nThese safe operations are defined in: \n* [Nats](src/main/scala/fragile/nat/package.scala) as **safeN**\n* [Lists](src/main/scala/fragile/list/package.scala) as **safeL**\n* [Ints](src/main/scala/fragile/int/package.scala) as **safeI**\n\n### Manual eta-expansion\n\nAs in the value world, on type level there has to be eta-expansion as well.\nThere has to be a way to convert from a type level function definition, to a function value-like type level entity.\n\nBasically a way to convert a type definition to a [Function](src/main/scala/fragile/function/Function.scala) type.\n\nThis is done manually, compiler has no idea what's going on, it may be improved by a Scala Compiler Plugin, but meh.\n\n``` Scala\ntype increase[N \u003c: Nat] = N + _1\n\ntype expanded = eta[increase]\n```\n\nThen all of the functions for composition are available.\n\n### Laws\n\nTests are organized as law sets.\n\nTo run tests simply compile them.\n\nLaws contain all of the function usages and scenarios:\n* [Bool](src/test/scala/fragile/bool/laws.scala)\n* [Function](src/test/scala/fragile/function/laws.scala)\n* [Int](src/test/scala/fragile/int/laws.scala)\n* [List](src/test/scala/fragile/list/laws.scala)\n* [Nat](src/test/scala/fragile/nat/laws.scala)\n\n## So?\n\nWhat's next, you may ask?\n* Implement **Map** as [**List**](src/main/scala/fragile/list/List.scala) of [**Products**](src/main/scala/fragile/product/Product.scala)\n* Upgrade [**List**](src/main/scala/fragile/list/List.scala) to handle [**Ints**](src/main/scala/fragile/int/package.scala)\n* Upgrade [**Ints**](src/main/scala/fragile/int/package.scala) to support **Rationals**\n\nBut I am too lazy. \n\n:(\n\n## Copyright and License\n\nCopyright © 2017 Dmytro Stechenko\n\n[GPL License](http://www.gnu.org/licenses/gpl.html)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdstechenko%2Ffragile","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdstechenko%2Ffragile","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdstechenko%2Ffragile/lists"}