{"id":16323073,"url":"https://github.com/yamadapc/simple-warp-server","last_synced_at":"2025-10-31T21:30:27.726Z","repository":{"id":66319706,"uuid":"42326706","full_name":"yamadapc/simple-warp-server","owner":"yamadapc","description":"An unfinished study comparing JavaScript and Haskell servers.","archived":false,"fork":false,"pushed_at":"2015-09-15T23:13:25.000Z","size":148,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-12-24T11:58:04.411Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yamadapc.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":"2015-09-11T18:55:23.000Z","updated_at":"2020-03-10T05:19:28.000Z","dependencies_parsed_at":"2023-03-08T13:15:28.461Z","dependency_job_id":null,"html_url":"https://github.com/yamadapc/simple-warp-server","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/yamadapc%2Fsimple-warp-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yamadapc%2Fsimple-warp-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yamadapc%2Fsimple-warp-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yamadapc%2Fsimple-warp-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yamadapc","download_url":"https://codeload.github.com/yamadapc/simple-warp-server/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239231086,"owners_count":19603990,"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":[],"created_at":"2024-10-10T22:53:51.680Z","updated_at":"2025-10-31T21:30:27.668Z","avatar_url":"https://github.com/yamadapc.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"A simple Haskell server\n=======================\nAn unfinished study comparing JavaScript and Haskell servers.\n\n## A JavaScript primer\nHere's a node.js HTTP server, taken from the [node.js homepage](https://nodejs.org):\n```javascript\nvar http = require('http');\nhttp.createServer(function(req, res) {\n  res.writeHead(200, {'Content-Type': 'text/plain'});\n  res.end('Hello World\\n');\n}).listen(1337, '127.0.0.1');\nconsole.log('Server running at http://127.0.0.1:1337/');\n```\n\nIt's simple, small and readable. It gets even more readable if you put it like\nso:\n```javascript\nvar http = require('http');\n\nfunction handleRequest(req, res) {\n  res.writeHead(200, {'Content-Type': 'text/plain'});\n  res.end('Hello World\\n');\n}\n\nhttp.createServer(handleRequest).listen(1337, '127.0.0.1');\nconsole.log('Server running at http://127.0.0.1:1337/');\n```\n\nFirst comes an import from the `http` module. That's all you need to write it,\nwhich is because the `node.js`' core libraries are really extensive. My\nimpression, on `node.js`' case of having really broad core libraries, it seems\nthat there's a certain limitation on how far you can express certain concurrent\nscenarios, or computation, really. It's because node.js is a relatively\nhigh-level platform.\n\n\nThe core of the server is the `http.createServer` call. It takes a callback\nfunction of type `(http.IncomingMessage, http.ServerResponse)` to nothing,\nwhich gets called every time a request comes in. The body of the\n`handleRequest` function is just a couple of method calls over the\n`ServerResponse` instance that gets passed in as an argument.\n\nThere's yet another class underneath this API, `http.Server`, you could rewrite\nit as:\n```javascript\nvar http = require('http');\n\nvar server = new http.Server();\n\nserver.on('request', function(req, res) {\n  res.writeHead(200, {'Content-Type': 'text/plain'});\n  res.end('Hello World\\n');\n});\n\nserver.listen(1337, '127.0.0.1');\n```\n\nThis is a very common idiom in JavaScript. `http.Server` is actually an\ninstance of `events.EventEmitter`, which is the `node.js` API for JavaScript's\nevent listening pattern.\n\nI like the example server and that it hides its complexity really well in\nreally well designed and clean manner. `node.js` style is usually a nice mix of\nvery object oriented structures, with somewhat functional APIs here and there.\n\nAnd a lot of really popular modules are very object oriented (whether it shows\nor not). In `mongoose`'s case this is very clear, it provides a modeling system\nfor database entities and the logic related to them. It has support for\nattaching instance methods, static methods and more. It even has a plugin\nsystem, which will either work as a `mixin` of some kind or go the monkey\npatcher way and have fun with some internal, esoteric hack.\n\nHere's an example \"class\" (`Model` actually - and here JavaScript gets unique\nabout inheritance, because this isn't standard prototypical inheritance\nunderneath) definition using `mongoose`:\n```javascript\nvar mongoose = require()\n\nvar userSchema = new mongoose.Schema({\n  firstName: [{ type: String }]\n  lastName: [{ type: String }]\n})\n\nuserSchema.methods.fullName = function() {\n  return this.firstName + this.lastName;\n};\n\nvar User = mongoose.model('User', userSchema);\n```\n\n`superagent` exposes a builder API, `mocha` uses a `Mocha` god class which uses\nseveral other classes (`Runner`, `Spec`, `Reporter` - which is even abstract -,\netc.). I found this reliance on OOP for this bunch of Node.JS libraries to\ncontrast in an interesting way to the statement JavaScript is a very _lisp-like_\nlanguage - not that it isn't.\n\n- - -\n## The Haskell take\n\nLet's look at a Haskell Warp server:\n```haskell\n{-# LANGUAGE OverloadedStrings #-}\nimport Network.HTTP.Types\nimport Network.Wai\nimport Network.Wai.Handler.Warp\n\nmain :: IO ()\nmain = do\n    putStrLn \"Server running at http://127.0.0.1:9000\"\n    run 9000 app\n\napp :: Application\napp _req respond = respond $ responseLBS status200 headers body\n where\n   headers = [ (\"Content-Type\", \"text/plan\")]\n   body = \"Hello World\"\n```\n\nIt's not so far from the Node.js server. `app` is like our server callback in\nNode.js. It takes a `_req` object and a `respond` callback function.\n\nIn way, we could make it more _readable_ by using similar naming to the Node.js\nexample:\n```haskell\nmain = do\n    putStrLn \"Server running at http://127.0.0.1:9000\"\n    run 9000 handleRequest\n\nhandleRequest _req respond = respond $ responseLBS status200 headers body\n where\n   headers = [ (\"Content-Type\", \"text/plan\")]\n   body = \"Hello World\"\n```\n\nEven though Haskell is a super typed language, we can omit the type signatures.\nIt'll just infer them.\n\n**TODO** Keep writting about this.\n\n## License\nEverything under this repository is licensed under the GPLv2 license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyamadapc%2Fsimple-warp-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyamadapc%2Fsimple-warp-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyamadapc%2Fsimple-warp-server/lists"}