
Simple-twitter: A bare-bones Twitter clone implemented in a single file - revskill
https://github.com/Gabriel439/simple-twitter/blob/master/Main.hs
======
apetresc
A note to those who might dismiss this without looking at it carefully because
you assume it's just some SPA that mocks the Twitter UI: it's actually a
NixOps file (with everything inlined) that deploys the entire stack, including
a full backend and database.

~~~
cblum
This is the first time I’m seeing that. It’s so beautiful. It’s elegant. I can
understand it.

Why can’t the world move in that direction, instead of the insane Kubernetes
hype that’s prevalent these days?

~~~
Thaxll
Because this is a toy demo that doesn't do anything, in the real world you
need much more that than just to do something simple.

Also it looks "beautiful" to your eye, from a programming perspecting it looks
really un-readable if you don't use FP.

[https://github.com/Gabriel439/simple-
twitter/blob/master/Mai...](https://github.com/Gabriel439/simple-
twitter/blob/master/Main.hs#L174)

~~~
adrusi
_from a programming perspecting it looks really un-readable if you don 't use
FP._

I don't mean this as a slight, and I myself am slacking in the same regard,
but it's depressing to me that this attitude is so prevalent among
professionals.

There might be some good engineering reasons that tools like Docker and
Kubernetes have much more traction than Nix, but "it's unfamiliar if you don't
use FP" is a terrible one. It doesn't require that much investment to become
familiar, and there seems to be many fantastic advantages to functional
approaches.

Why does our industry tolerate this laziness?

~~~
chongli
_but "it's unfamiliar if you don't use FP" is a terrible one_

I get the sense that there is a large contingent of programmers who feel
disdain for mathematics and FP gets caught in the crossfire. It’s unfair
toward both mathematics and functional programming.

I would love it if North American culture could adopt a better attitude toward
mathematics in general. I think far too many people decide they’re bad at
mathematics at some point in high school and never look back. This attitude is
far less prevalent in many Asian cultures, where the emphasis is put on hard
work instead of talent.

~~~
greggman2
I know no good math teachers. Most math teachers pre-college don't know the
material themselves. I still don't know why something is "efficient with" (a
coefficient). And every time I try to get into any math there's 79 unspecified
prerequisites I supposedly need to understand all the jargon. 3blue1brown is
preaching to the choir AFAIK. I get lost trying to watch his videos as they
also expect you already know the material.

~~~
ColinWright
> _I still don 't know why something is "efficient with" (a coefficient)._

I can't parse this - would you care to expand on it?

> _3blue1brown is preaching to the choir AFAIK. I get lost trying to watch his
> videos as they also expect you already know the material._

If you care, you can always track back to earlier material and build your
knowledge. Most people I know in a similar situation to yours don't actually
care, and won't actually put in any effort.

And that's a reasonable choice. There are places where math is hard, needs
work, and most people have come to a point where they feel that the effort
won't be worth it, that the ROI isn't there. But if that's your decision, then
own it.

If that's not your decision, and you actually want to know more, there are
things you can do about it.

FWIW, I know a lot of really good math teachers, but I agree that there are
also some really poor teachers. If yours were bad then I feel bad about that,
although there's nothing I can do about your experience in the education
sector. What you do about it now, if anything, is up to you.

~~~
Aaargh20318
> There are places where math is hard, needs work, and most people have come
> to a point where they feel that the effort won't be worth it

The problem with math is that it's seems much harder than it actually is.
Every time I have to look into some specific math I haven't worked with before
I spend a lot of time decoding what they actually mean. Usually what is
happening is not that difficult at all, mathematicians just insist on writing
it down in the most convoluted and incomprehensible way imaginable.

It's like they took every bad coding practice and applied it all to math. Why
have descriptive variable names if you can just use random greek letters ? Why
give a function or operation a name at all if you could make up some weird
symbol instead ? And of course you want those symbols to have different
meanings depending on context. Imagine if programmers worked like that and
wrote everything as obfuscated C++ code, because fuck you.

~~~
ColinWright
> _Why have descriptive variable names if you can just use random greek
> letters?_

This is a common complaint I see from programmers all the time. However, I've
seen people trying to do real maths with descriptive names, and it fails very,
very quickly.

This is by no means comprehensive, but as a (probably thought) experiment, try
writing reasonable complex code without variable name completion. You write
the same variable name over and over and over, and after a while you realise
that since this variable is only use in this screenful or two of code, it's
easy enough just to use a short name and know what it is, because you're only
thinking about it here, in this context.

I'm not going to try to defend mathematical notation in general because there
are enormous inconsistencies, many of which are historical, accidental, and
indefensible.

But when you're _doing_ the maths it becomes tolerable, then usable, then
actively helpful. It's like the parentheses in Lisp - all newbies complain
about them, and those versed in the art know that after a while they not only
don't matter, they are a genuine positive.

But unless you take the time to _do_ the math, that won't happen for you. That
makes it sound like a deliberate barrier, but it's not, it really isn't.

~~~
Aaargh20318
> This is by no means comprehensive, but as a (probably thought) experiment,
> try writing reasonable complex code without variable name completion.

So why don't math tools have variable name completion ? and/or why insist on
still doing things on paper in 2019 ?

The other things about variable names is that they force you to think about
what a variable actually contains. This in itself is very helpful not only for
others reading your work, but also for yourself when trying to grasp a
problem.

~~~
ColinWright
The research mathematicians I work with just stare in incomprehension at the
idea of doing their work on any computer-mediated system. Yes, there are
things that can be done, and yes, computer proof-assistants have made huge
strides, and yes, there are always people at the cutting edge doing amazing
work.

But your everyday research mathematician will just stare in disbelief.

I don't know your background, your profile is empty, but it sounds like you
are someone who genuinely has no idea of how research in math works, and
therefore feel that you really must have a better way of doing things. And
maybe you have. But speaking as someone who has a PhD in pure math, and who
has worked in safety critical software, I can only say that so far everything
you're suggesting just really doesn't make sense.

The reason that for centuries mathematicians use single letter glyphs to
represent the things they're dealing with is because it is, for the purpose of
doing the work, the most effective thing to use.

~~~
Aaargh20318
> The research mathematicians I work with just stare in incomprehension at the
> idea of doing their work on any computer-mediated system. Yes, there are
> things that can be done, and yes, computer proof-assistants have made huge
> strides, and yes, there are always people at the cutting edge doing amazing
> work.

I'm not talking about computer assisted proofs or anything like that. Just
using a readable syntax and the mathematical equivalent of a word processor
would be an enormous step forward. No one is writing books in cursive with a
fountain pen anymore either, which is basically analogue to what
mathematicians are still doing.

~~~
ColinWright
> _I 'm not talking about computer assisted proofs or anything like that._

No, I'm not talking about proof assistants either, I'm talking about actually
doing math using any kind of computer system.

> _Just using a readable syntax and the mathematical equivalent of a word
> processor would be an enormous step forward._

Do you have any idea of how to do that? I've done research in math, and I've
written software for safety critical systems. I don't know how to create a
system like a word processor for math that would let me actually do the math.

Do you know how to do that? If so, please, let me know.

------
joewrong
" ORDER BY tweet.time DESC "

sign me up

~~~
mc3
Whether it is the lack of an ORM or lack of a "algorithm" that pleases you,
this comment has made my day :-).

~~~
hombre_fatal
I believe they're referring to the lack of algorithmic sorting.

~~~
Jaxan
I’m not even sure what to think of the term “algorithmic sorting.” Is
quicksort considered as algorithmic sorting ... ?

~~~
hombre_fatal
I'm referring to "algorithmic" in its negative usage as short-hand for what
you can see as of late with regard to Twitter, Youtube, and Facebook's
suggestion engines where more complex sorting and filtering is happening than
a simple ORDER_BY.

Sure, not the best short-hand, but it seems most people understood what I
meant.

For example,
[https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...](https://hn.algolia.com/?dateRange=all&page=0&prefix=true&query=algorithm%20youtube&sort=byPopularity&type=story)

Like this submission:
[https://news.ycombinator.com/item?id=20184282](https://news.ycombinator.com/item?id=20184282)
where people will shorten the "evil" to just "the algorithm".

------
TheUndead96
There are a lot of very strong opinions in this thread on whether this code
would be "production ready". I don't think that is the point here. This is
awesome because of its brevity, it is like writing a ray tracer in 100 lines
of C. It demonstrates that a task which might be perceived to highly
complicated can be reduced to a file, of which the size many of us would just
define a single class in such a system.

------
blakesterz
It might be better to change the link to the main README:

[https://github.com/Gabriel439/simple-
twitter](https://github.com/Gabriel439/simple-twitter)

------
akersten
It's a nice demo. But there seems to be a surprising lack of validation? Seems
like anyone can delete any other user, or post as anyone else, etc. Then
again, I can't read Haskell, so I don't know if there's something preventing
that at a higher level than the endpoint logic.

~~~
whateveracct
Doesn't look like there is. I think the idea is for this to be a nontrivial
example of a full-stack Haskell+Nix(Ops) project. The Twitter part is meant to
be more familiar that robust.

It's fair to argue auth should be included in a nontrivial example though. I
honestly don't think it would add that much clutter either. Although unlike
the other components, I don't know if there's a simple off-the-shelf Haskell
solution for auth.

~~~
wyager
Servant (the typed routing system being used here) has pretty awesome and
robust authentication support. I bet it could be added without too many
additional lines.

------
jpochtar
Small, easy to write/maintain approaches are at an evolutionary disadvantage
vs classically "enterprise" styles.

Easier to work with -> fewer people needed -> fewer people hired -> fewer
people learn -> fewer people know.

Now there's fewer people in the market who know Simple, vs many people who've
learned OverEngineered (TM). Leadership wants to pick a language/style they'll
be able to hire for as-needed. OverEngineered has a much larger talent pool.

------
kyllo
Love the use of quasiquotation here:

    
    
        import Database.PostgreSQL.Simple.SqlQQ (sql)
        ...
    
        let index :: Handler Markup
            index = do
                tweets <- query_ [sql|
                    SELECT "user".name, tweet.contents
                    FROM           "user"
                        INNER JOIN user_tweet ON "user".name = user_tweet."user"
                        INNER JOIN tweet      ON user_tweet.tweet = tweet.id
                    ORDER BY tweet.time DESC
                |]

------
cocochanel
This made me want to learn haskell. What a clean code. Pleasure to read.

~~~
samcodes
Yeah, another comment said this is “unreadable” if you don’t do FP... I have
done a little lisp + Elixir, but 99% of my coding has been in C-descendant
languages and this was definitely readable.

~~~
dmitriid
It's readable because we know what we're expecting. Had the logic been just a
tad more complex (e.g validation of input, login flows etc.), it would quickly
become unreadable _and_ unmaintainable to anyone not familiar with FP, or
specifically Haskell:

\- there are fifteen LANGUAGE directives (what do they all bring?)

\- there's an ungodly amount of ASCII-art: What do any of these do, and in
which contexts: ! @ :> :<|>

And so on: just three things that caught my eyes looking at the code on my
phone

~~~
wyager
> just a tad more complex (e.g validation of input, login flows etc.)

Servant (the routing library being used here) has pretty great and clean
authentication support.
[https://docs.servant.dev/en/stable/tutorial/Authentication.h...](https://docs.servant.dev/en/stable/tutorial/Authentication.html)

As for validation of input, what do you mean? Haskell tends to excel there as
well, with the availability of parser combinator libraries like Attoparsec.

> LANGUAGE directives (what do they all bring?)

In a real project you hide these in a config file for your project. They're
usually well documented, and you can usually guess what they're doing from the
name once you have some context.

> What do any of these do, and in which contexts: ! @ :> :<|>

All of those except @ are just functions or types. You can look up what they
do in the same way you would look up what any other function does. @ is the
only one that's a syntactic operator, and it has 2 meanings depending on
context. It's either specifying what a type variable should be, or it's
pattern matching and binding a name at the same time.

~~~
dmitriid
> has pretty great and clean authentication support.
> [https://docs.servant.dev/en/stable/tutorial/Authentication..](https://docs.servant.dev/en/stable/tutorial/Authentication..).
> > with the availability of parser combinator libraries like Attoparsec. >
> you hide these in a config file for your project.

etc. etc.

You're not helping the cause of "this is 99% readable" ;) If you add proper
authentication and parser combinators [1], and configs, and.... It becomes
anything _but_ readable to a person without specific Haskell and very specific
library knowledge.

And yes, I do have exposure to FP having worked with Erlang for a number of
years.

I also seriously detest the unexplained love for ASCII art among many lib
authors in the FP space. Servant is one such example: :> :. :<|> ! At this
point, why not use J :)

[1] By the way, unless I'm mistaken, there's next to zero useful documentation
on Attoparsec, there's only barebones package documentation. And no, you don't
validate data using parser combinators unless your data is only strings that
resolve to some DSL.

~~~
verttii
Why would Haskell need to be readable by people who don't know Haskell?

~~~
cerberusss
Well, it does lower the barrier for entry.

------
xwdv
I hope this is only the beginning of a series of popular web apps and social
networks all recreated as pithy single file documents. Next should be
Facebook.

~~~
james_s_tayler
YouTube would be good too.

------
dom96
This is cool and reminds me of the Twitter clone[1] I included as a coding
exercise in my book[2]. It's a very good way to learn as a basic Twitter clone
is relatively simple to implement.

1 - [https://github.com/dom96/nim-in-action-
code/tree/master/Chap...](https://github.com/dom96/nim-in-action-
code/tree/master/Chapter7/Tweeter)

2 - [https://book.picheta.me](https://book.picheta.me)

~~~
jedimastert
A basic twitter clone sounds like a reasonable Hello World for new web
frameworks

~~~
sansnomme
Only if you include stuff like auth and migrations.

[https://github.com/gothinkster/realworld](https://github.com/gothinkster/realworld)

It's pretty easy to tell which frameworks are mature and which are not simply
by looking at how many wheels that need to be reinvented.

~~~
jedimastert
I don't know that I agree, or at least that's not always the goal. I've found
that the more "wheels" already in the framework, the more opinions the
framework has, and sometimes I just need something dead simple.

Laravel, for instance, has so many really nice wheels, but it's organization
can feel restrictive at times.

web.py, on the other hand, has basically no wheels but I can drop into a
project really quick.

Maturity is a spectrum, and sometimes you don't need a wagon when a bike will
do.

~~~
sansnomme
There are tons of Flask/Sinatra level abstraction frameworks. They bring
nothing new to the table. Stuff like auth and migrations are difficult
problems, which is exactly why you need a framework. Any halfway decent web
dev can cobble together yet another expressjs lookalike, but there are few
that can reliably build Devise type authentication solutions. Ever wondered
why most build-a-blog web framework demo tutorials tend to conveniently skip
user registration/auth?

------
k__
Haha, awesome.

It would be awesome if Nix, NixOS and NixOps replaced the current mess that is
Docker and K8s.

------
gulperxcx
Are there any screenshots of what this looks like when in use?

~~~
Gabriel439
I just added one. Thanks for the suggestion!

------
mark_l_watson
I really like the code. Sometimes I have problems following other people’s
Haskell code but I found this web app to be very readable. Good stuff.

------
kgthegreat
Slightly related - If you want a pre-categorised tweets feed with ability to
add new categories, I have written one -
[http://trysensible.com/](http://trysensible.com/) (Open source
[https://github.com/kgthegreat/sensible](https://github.com/kgthegreat/sensible)).
It comes with some standard categories such as politics, sports etc. but you
can add whatever categories you want such as - music, academia and start
adding your own curated list of keywords to support this category. This is
written in golang and is open source
[https://github.com/kgthegreat/sensible](https://github.com/kgthegreat/sensible)

------
cryptozeus
Can someone explain more ? I am not familiar with haskell. So is this like a
Twitter like functional demo ?

------
grizzles
This is a really nice one: [https://github.com/rafaelalmeidatk/twitter-
fullstack-clone](https://github.com/rafaelalmeidatk/twitter-fullstack-clone)

------
cyborgx7
A lot of people complaining that this wouldn't be able to hold the load of the
original thing like that. I'd argue that all platforms attempting to be all-
encompassing is a big problem right now. Maybe a single instance of a platform
should really just accept as much load as this could handle in this form. They
could federate with eachother to replicate the massive connected structure.

------
beders
Ok, CLJ/CLJS, your turn ;)

------
gigatexal
Love the raw sql queries here.

------
zemnmez
I learned more about haskell reading this than I ever have from anything else

------
bitlax
Might be nice if this title was changed. This is a toy app which is guaranteed
to blow up at scale, but if the point is to show off a particular stack then
maybe it should say so.

~~~
travbrack
The fact that it's in a single file implies this. I don't think anyone would
think they are trying to claim they can replace all of Twitter's production
code with this single file.

~~~
rco8786
I don’t think that either. But someone HN made a very spirited argument a few
years ago that he could build and run Twitter in no more than 4 servers.

~~~
hokumguru
Depends on the servers...

~~~
rco8786
I guess in theory that's true, but not any commercially available server I'm
aware of.

------
omnifischer
OT very useful [https://nitter.net](https://nitter.net)

------
asdfasdfdavid
Awesome slides, thanks for explaining!

------
webscalist
needs photo and video upload

~~~
Gabriel439
I just added a screenshot to the README

