{"id":19408269,"url":"https://github.com/vivshaw/three-wise-monkeys","last_synced_at":"2025-04-24T09:31:51.950Z","repository":{"id":49880639,"uuid":"375232291","full_name":"vivshaw/three-wise-monkeys","owner":"vivshaw","description":"You've heard of the SKI combinators... How about the 🙊🙉🙊 combinators?","archived":false,"fork":false,"pushed_at":"2021-06-09T18:04:37.000Z","size":19,"stargazers_count":34,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-03T03:07:54.889Z","etag":null,"topics":["buddhism","emoji","haskell","obfuscated"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vivshaw.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":"2021-06-09T05:06:53.000Z","updated_at":"2025-02-05T20:51:22.000Z","dependencies_parsed_at":"2022-09-21T15:23:41.563Z","dependency_job_id":null,"html_url":"https://github.com/vivshaw/three-wise-monkeys","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/vivshaw%2Fthree-wise-monkeys","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivshaw%2Fthree-wise-monkeys/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivshaw%2Fthree-wise-monkeys/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vivshaw%2Fthree-wise-monkeys/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vivshaw","download_url":"https://codeload.github.com/vivshaw/three-wise-monkeys/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250600716,"owners_count":21457017,"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":["buddhism","emoji","haskell","obfuscated"],"created_at":"2024-11-10T12:05:49.805Z","updated_at":"2025-04-24T09:31:51.627Z","avatar_url":"https://github.com/vivshaw.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🙈🙉🙊 Three Wise Monkeys 🙈🙉🙊\n\nAn exercise in obfuscated Haskell vis-a-vis a primate proverb.\n\n## What does it do?\n\nThis program simply prints the text \"siddhartha\" using the [SKI combinator calculus](https://en.wikipedia.org/wiki/SKI_combinator_calculus). This is further obfuscated through the abuse of arbitrary Unicode identifiers, as well as the the C preprocessor.\n\nThe key to understanding how this works goes like so:\n\n```Haskell\n-- What the heck is this?\nwisdom See no e vil is (no -\u003e e -\u003e vil) -\u003e (no -\u003e e) -\u003e no -\u003e vil\n-- Well, take a look at the S combinator:\ntype S f x y = (f -\u003e x -\u003e y) -\u003e (f -\u003e x) -\u003e f -\u003e y\n-- Yup, the first monkey is just an obfuscated S combinator\n(🙈) :: See no e vil\n\n-- So this one should be easier:\nwisdom Hear no evil is no -\u003e evil -\u003e no\n-- Compare to the K combinator:\ntype K x y = x -\u003e y -\u003e x\n-- Yup, the second monkey is just the K combinator (a.k.a const)\n(🙉) :: Hear no evil\n```\n\nFrom here, we can construct the I combinator 🙊 (a.k.a. `id`), and have the whole of the SKI combinator calculus at our disposal. Additionally, I define [the B and C combinators](https://en.wikipedia.org/wiki/B,_C,_K,_W_system) for ease of use, as 🐵 and 🐒 respectively. From that point the rest is not too complex. If you wish to see which chunks of code correspond to which letters, simply undo all the ASCII art made from the monkeys and linebreak each time you see a ton of closing parenthesis, then study the repeating monkey patterns leading up to them. It will become clear that there are 10 main blobs (one for each character in \"siddhartha\") and each repeats the pattern `((🙈)(🐵)` equal to the character's ASCII codepoint minus 10. This rather telling pattern should make it obvious [how the rest works](https://www.reddit.com/r/haskell/comments/ypcu7/hello_world_in_ski_combinator_calculus/c5y5uvq/).\n\n## Obfuscation techniqes\n\n### Unicode abuse\n\nHaskell is generous. Haskell loves you. Haskell allows arbitrary Unicode characters in identifiers and operators, because you deserve it.\n\n - Type names and variable names can have any Unicode letter or number in them, with the caveat that types must start with a `C`apital letter, and variables must start with a `l`owercase letter. As it turns out, you can use things like Hanzi, hangul, or kana as well- Haskell simply treats them as lowercase letters.\n - Operator names can have any non-special unicode symbol (pretty much everything except ``()|,;[]`{}_:\"'``), including emoji. However YMMV - some symbols or combinations thereof will make GHC wig out, especially anything 'bracket-like'.\n\n### `{-# LANGUAGE CPP #-}`\n\nWith this GHC extension, we can run the C preprocessor on our Haskell source before compilation. This allows a large number of unusual substitutions that *don't* need to follow the rules of regular Haskell syntax, but *do* require obeying C identifier rules. As an added bonus, the behavior may be platform-dependent based on whether your system runs `clang` or `gcc`.\n\n### the SKI combinatory calculus\n\nanything written with combinatory logic is obfuscated by default lol\n\n## Do you have any suggestions to further beautiful, comfound, or obfuscate?\n\nPR's welcome if there's any other ~\"FUN\"~ things you can make GHC do. I didn't look too far into TH, rewrite rules, or RebindableSyntax.\n\n## Credit where credit is due\n\nInspiration is due to Sami Hangaslammi's [SKI Hello World](https://gist.github.com/shangaslammi/3438688) and the [technique used to construct it](https://www.reddit.com/r/haskell/comments/ypcu7/hello_world_in_ski_combinator_calculus/c5y5uvq/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvivshaw%2Fthree-wise-monkeys","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvivshaw%2Fthree-wise-monkeys","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvivshaw%2Fthree-wise-monkeys/lists"}