It does.
How many PhDs does one require to understand/correct/debug all the :> and :<|> etc.?
> debug
But the whole point of a good compiler is that it tells you when you're wrong! (Instead of having to write hundreds of tests (and thousands of Node test runners).)
> :> and :<|>
You can just treat them as syntax, like the largest proportion of every other language, but with the opportunity of actually being able to write things like that yourself later.
Observe:
type API = "polls" :> Get '[JSON] [Poll]
:<|> "polls" :> Capture "question_id" Int :> Get '[JSON] Poll
:<|> "polls" :> Capture "question_id" Int :> "results" :> Get '[JSON] PollResults
The :> operator separates parts of a path, and the :<|> separates different URL patterns. This is the equivalent of this API from the Django documentation: urlpatterns = [
# ex: /polls/
url(r'^$', views.index, name='index'),
# ex: /polls/5/
url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
# ex: /polls/5/results/
url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results')
]
The only difference is it has less regexes in it, is capable of being checked for nonsense by a compiler much smarter than me, and gives you the aforementioned "server for free". I have had URL pattern-match errors with Django in the past, and having your compiler check that there aren't any is excellent.Easier to maintain? Check.
Easier to read? Check. (If nothing, because of the lack of regexes.)
Defines the response type too? Check.
Easy to refactor? Check! Tired of typing "polls" at the beginning? Just lift it out: turn
type API = "polls" :> Get '[JSON] [Poll]
:<|> "polls" :> Capture "question_id" Int :> Get '[JSON] Poll
:<|> "polls" :> Capture "question_id" Int :> "results" :> Get '[JSON] PollResults
into type API = "polls" :>
( Get '[JSON] [Poll]
:<|> Capture "question_id" Int :> Get '[JSON] Poll
:<|> Capture "question_id" Int :> "results" :> Get '[JSON] PollResults
)
Types are first-class :)> How many PhDs does one require to understand/correct/debug all the :> and :<|> etc.?
Definitely less than it takes to become comfortable with the quirks of literally everything in JS: perhaps you should give something an honest shot before telling people who have derived real-world benefits from using it in production that it's useless?
So, basically, "learn this thing without understanding what it does" :-\
Reminds me of teaching Java to newbies: "oh, just type this syntax, you have to memorize it, don't worry about it".
> Definitely less than it takes to become comfortable with the quirks of literally everything in JS: perhaps you should give something an honest shot before telling people who have derived real-world benefits from using it in production that it's useless?
A real app is not just "hey, memorize this DSL and type it". I've found Haskell unapproachable on multiple occasions. And yes, I've completed my obligatory "Haskell from first principles" and "Learn You a Haskell for Great Good!" :)
If you've picked up the stuff in LYAH, you're ready to learn what type operators are (that's where :> and friends come from, they're just things like Maybe but written infix, so they're probably defined as
data a :> b = ColonPointyThing a b
or something like that.) Servant then pattern-matches on these types, essentially. For instance, if I can handle an API that serves endpoint A, and one that serves endpoint B, I can handle an API that serves both:
instance (Handler A, Handler B) => Handler (A :<|> B) where
handle req = ...
That's the idea.You'd hardly expect a beginner to pick up, I dunno, using React and Redux on a Webpack hot-reloadable setup on day 1 of "Javascript 101", but React is one of the best ways to sell modern web development (at least when I've been buying).
> So, basically, "learn this thing without understanding what it does" :-\
> Reminds me of teaching Java to newbies: "oh, just type this syntax, you have to memorize it, don't worry about it".
I don't think what's recommended is the same.