[cwn] Attn: Development Editor, Latest OCaml Weekly News
Alan Schmitt
alan.schmitt at polytechnique.org
Tue Mar 26 08:22:44 PDT 2019
Hello
Here is the latest OCaml Weekly News, for the week of March 19 to
26,
2019.
Table of Contents
─────────────────
textrazor 0.1
'Rails on OCaml'
Bucklescript 5.0 released
Tablecloth - a new standard library for OCaml and ReasonML
Easy_logging 0.2
OCaml meetup in SF on Tuesday 3/26
Yojson 2.0.0 plans
iso639 - language codes
Other OCaml News
Old CWN
textrazor 0.1
═════════════
Archive: <https://discuss.ocaml.org/t/ann-textrazor-0-1/3527/1>
Richard Degenne announced
─────────────────────────
I am very proud to announce my very first OCaml package, in the
form
of `textrazor', an OCaml wrapper for the [TextRazor] API.
<https://github.com/Richard-Degenne/ocaml-textrazor/>
This first release supports:
• The main analysis endpoint, with most options and sensible
defaults
built-in;
• The account endpoint.
I am sure that a lot can be done to improve the code. Please
feel free
to comment, open issues or even submit pull requests about
anything if
you feel like it. :)
I've set up a (non-exhaustive) roadmap of features I will be
working
on in the coming days. Once again, contributions of any kind are
most
welcome.
<https://github.com/Richard-Degenne/ocaml-textrazor/projects/1>
[TextRazor] <https://www.textrazor.com/>
'Rails on OCaml'
════════════════
Archive: <https://discuss.ocaml.org/t/rails-on-ocaml/3537/1>
Yawar Amin said
───────────────
I'd like to discuss @jasim 's [post] a bit. It's a great
conversation
starter but it got me thinking that we need to actually look at
how
such a framework would _look and feel_ from the user's (i.e. the
web
dev's) perspective. And whenever I think of web dev, the pattern
I
keep coming back to is the tried-and-true MVC. And I really like
how
Phoenix has done it, so I keep wanting to borrow some ideas from
there. So to me, here's what a nice project layout might look
like
(this is native so all module names are disambiguated by dune):
┌────
│ dune-project
│ README.md
│ src/
│ dune
│ model/
│ dune
│ User.re
│ service/
│ dune
│ User.re
│ web/
│ controller/
│ dune
│ User.re
│ dune
│ middleware/
│ ...
│ Server.re
│ template/
│ not-found.mustache.html
│ not-found.mustache.json
└────
And here are a couple of example usages from this imaginary
project:
<https://gist.github.com/yawaramin/f0a24f1b01b193dd6d251e5e43be65e9>
So in the above snippet, the main app is set up in
`src/web/Server.re'. What I wanted here was a really
minimalistic but
also extensible way to set up routes and middlewares. And to me
the
way that makes the most sense to handle routing in OCaml is
pattern-matching (kudos to the ReasonReact team for coming up
with
that simple and elegant design). So the `Server' module is the
heart
of the app, but this being OCaml, there's no magic involved–the
route
handlers are just functions from routes and requests to
(promises of)
responses.
Requests should contain things like the headers, query params,
cookies, session, flash, body, etc.
Responses should be constructed programmatically (using
`ReWeb.Response.{make,makeAsync}') or from ocaml-mustache
templates
(see `template/' subdirectory). The response constructor
function
should take optional arguments for status, headers, cookies,
etc. with
appropriate defaults.
Middleware should be functions that take a response and return a
promise of _request_ (which might be a _cancelled_ request); in
this
way they are composeable (much like Elixir's plugs).
I haven't touched on data access here; to be honest I'm not very
familiar with the OCaml database libraries at the moment, but I
am
leaning towards Caqti since it seems to be active, and supports
the
popular OSS DBs as well as Lwt.
Scaffolding would be great to have and it would be great if dune
or
opam would let us do that (e.g. `opam new my-app --scaffold
reweb'),
but in the meantime we can probably get away with maintaining
example
starter projects which people can copy to start with.
Lots of this is off the top of my head but what I'm trying to do
here
is uncover an _ergonomic_ design for a web framework, based on
learnings from recent successful frameworks. I think a large
part of
it would be just giving users a 'blessed stack' of libraries to
start
with, so they don't have to go hunting throughout the ecosystem
and
don't have to figure out and set up a project structure from
scratch
(where does the router go? where do the controllers go? where do
I put
the tests?). And so on.
P.S. the pattern-matching routers look _really_ nice in OCaml
syntax.
[post] <https://protoship.io/blog/rails-on-ocaml/>
RogerT asked and Yawar Amin replied
───────────────────────────────────
> Is it the only pattern? In fact, what are all the possible
> patterns?
Well, for example Eliom has a service-handler pattern for
creating
endpoints:
<https://ocsigen.org/eliom/6.6/manual/server-services>
There is [ocaml-webmachine] which treats endpoints as resources
that
are exposed according to a state machine.
There's [Cohttp] which treats the server as a single function
that
gets run by the event loop. It's up to users to define
abstractions on
top of that.
So I think there is no shortage of approaches to web servers in
OCaml.
[ocaml-webmachine]
<https://github.com/inhabitedtype/ocaml-webmachine>
[Cohttp] <https://github.com/mirage/ocaml-cohttp>
Gabriel Radanne then said
─────────────────────────
> Well, for example Eliom has a service-handler pattern for
> creating
endpoints:
Note that Eliom contains several pieces:
• The *web framework* indeed promotes this service-handler
pattern,
although that is fairly lightweight and flexible (and you can
basically treat it like cohttp and add your abstraction on
top, if
you feel like it)
• The *language*, on the other hand, is almost completely
model-agnostic, it only cares about making sure data-transfers
between client and servers are well typed, sound, and as easy
to do
as possible.
So far, the language and the framework are not as separate as I
would
like, but it's certainly on my todo-list to make all this more
modular.
Jasim A Basheer said
────────────────────
Thanks @yawaramin for framing this nicely and continuing the
conversation.
In my mind I wanted to design an _ideal_ framework, yet somehow
avoid
the [second-system effect] by basing the design on actual
application
needs. And so in service to this idealism I have wanted to build
a web
application in Haskell and borrow the best ideas they have to
offer. I
think it might never come to pass, so if there are people who
know how
the Haskell ecosystem approaches this, that'd be great to hear.
Since we have the opportunity to do something from scratch, it
might
be worth thinking what a futuristic framework should look
like. Otherwise we'll have to play catch-up with mature
alternatives,
repeating their mistakes, and not having anything new and
radically
better to offer to the world. Working on that kind of a project
might
not inspire the kind of passion it takes to bring something like
this
into production.
I think dhh's approach to Rails is worth emulating - [framework
must
be extracted, not envisioned]. So what kind of web applications
is
Rails ideally suited for, and what kinds does it make it
difficult and
unwieldy? And how can we have the best of all worlds?
Rails is built as a vehicle for [Basecamp], which is a project
management software. The major operations are create, read,
update,
and delete of database records. It is filled with forms, and a
simple
request-response cycle works well for most of them. The closer
the
application you're building is to a Basecamp, the more
affordances
Rails gives you. But if you're building say a WhatsApp clone
with
Rails, you're going against the grain of the system.
[second-system effect]
<https://en.wikipedia.org/wiki/Second-system_effect>
[framework must be extracted, not envisioned]
<https://dhh.dk/posts/6-why-theres-no-rails-inc>
[Basecamp] <https://basecamp.com>
ORM
╌╌╌
Since most operations are CRUD, Rails gives significant
developer
comfort when it comes to database operations, and that is thanks
to
its ORM. It gives a lazy interface to construct queries - they
are
first class values - and gets executed only at the last possible
moment. Rails follows the ActiveRecord pattern and I prefer it
over
having to construct SQL statements for mundane stuff. We can
always
drop down to raw SQL when needed, but for simple reads and
updates,
I've found ActiveRecord to be more ergonomic.
But would a simple layering like [mirage/orm] be fine, or are
Typed
ORMs like [pgocaml], which extracts database schema info in
compile
time and makes types out of them, worth looking into? Haskell
has
multiple such implementations and I hope they have converged on
some
Do's and Don'ts there.
[mirage/orm] <https://github.com/mirage/orm>
[pgocaml] <http://pgocaml.forge.ocamlcore.org/>
Database Migrations
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
I think Phoenix, Rails, Django, and even Java with [Flyway] have
all
converged over an identical pattern for database migrations and
there
is no wheel to be reinvented here.
[Flyway] <https://flywaydb.org/>
Streaming
╌╌╌╌╌╌╌╌╌
Rails support streaming by treating the response object as an
enumerator. This allows us to build pages that can immediately
start
sending data back to the client without having to wait till the
whole
page is built.
Concurrency, Evented vs Threaded vs Multi-process
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
My understanding is quite hazy on this. What is it going to be?
I know
I don't want every single one of my database call to be a
callback,
like we're forced to do in Node, which is now papered over by
async/await. But is it possible to build non-evented servers on
which
a WhatsApp can be built?
Background Jobs
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
Do we serialize background jobs outside the application - like
in
Sidekiq, which stores everything in Redis? Or is it possible to
spawn
off new processes like in Erlang? How do we scale processes or
jobs
across multiple servers? How about observability?
Templating
╌╌╌╌╌╌╌╌╌╌
Conventional string-interpolation with partials is much less
ergonomic
than writing reusable components and dealing with them as HTML
tags
like in JSX. It should be possible to use the same code to
render
pages both on the server and the client – React+JSX server-side
rendering does this really well.
Client-side code
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
Ocsigen seems to allow the ability to write functions that
execute on
both the client and the server transparently, while allowing
context-dependent behavior when necessary. It takes care of
maintaining and transferring state to and fro between server and
client, eliminating the need to write custom endpoints. I've
tried
pursuing the documentation and found it difficult to understand,
happy
to be corrected.
In my experience the majority of client-side code need to be
present
only on the browser, and treating the code paths separately is
clearer
to understand. What we need however is a better way to allow
data to
be passed around, which the next section addresses.
Client-side data
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
Rich web applications require hundreds of JSON endpoints with
varying
levels of granularity. GraphQL attempts to solve this by
creating a
declarative API, which express the schema of the data needed by
each
client request. Interesting waters there.
These are a set of questions I had in my mind when I wrote that
post. They are not terribly well thought out, but I'm hoping
those
with more clarity can chime in.
Bucklescript 5.0 released
═════════════════════════
Archive:
<https://discuss.ocaml.org/t/bucklescript-5-0-released/3540/1>
Hongbo Zhang announced
──────────────────────
See <https://bucklescript.github.io/blog/> for more details.
The cool
thing is that you can try it out within 20s everywhere using
cloud
service like <https://c9.io/>
`npm i -g bs-platform && bsb -init test && cd test && bsb'
Tablecloth - a new standard library for OCaml and ReasonML
══════════════════════════════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/tablecloth-a-new-standard-library-for-ocaml-and-reasonml/3528/1>
Paul Biggar announced
─────────────────────
Hey folks, I've been working on a standard library for OCaml and
ReasonML, which has the same API in both. This is to help us
with code
reuse between our OCaml backend and our ReasonML frontend.
It's called [tablecloth], and we wrote up an announcement
[here].
Would love to folks contributing back to it - if you're
interested
there's a long list of ways to help.
[tablecloth] <https://github.com/darklang/tablecloth>
[here]
<https://medium.com/darklang/tablecloth-a-new-standard-library-for-ocaml-reasonml-d29a73a557b1>
Easy_logging 0.2
════════════════
Archive: <https://discuss.ocaml.org/t/easy-logging-0-2/3551/1>
Sapristi announced
──────────────────
feeling that there was some lack of logging librairies for OCaml
(apart from the Logs module, which was a bit too complicated to
use
for me), I wrote a (hopefully) both easy to use and yet powerful
logging library, taking inspiration from the excellent Python
logging
package.
Some defaults are provided that allow logging to the stdout
and/or
files, but it is also possible to redefine you own handlers.
[Sources] and [Documentation] are provided.
Any comment or suggestion would be appreciated.
[Sources] <https://github.com/sapristi/easy_logging>
[Documentation]
<https://sapristi.github.io/easy_logging/easy_logging/>
Christian Lindig asked and Sapristi replied
───────────────────────────────────────────
I believe support for printf-style strings for creating
log messages would be useful. Formatting strings even when
they are not used because of the log priority can
introduce a performance concern, though.
I think I will eventually add support for format strings, but
for now
you can use the logging methods that take a lazy string as an
input,
for example
┌────
│ logging#ldebug ( lazy (Printf.sprintf "%s" mystring))
└────
see [lazy logging methods].
[lazy logging methods]
<https://sapristi.github.io/easy_logging/easy_logging/Easy_logging/Logging/class-logger/index.html#lazy-logging-methods>
Kevin Ji asked
──────────────
How does this compare to [Async's `Log' module], which is
generally
used as follows:
┌────
│ Log.Global.info "Message %d" count
│ Log.Global.warn_s [%message "Issue connecting to db" (db :
string)]
└────
[Async's `Log' module]
<https://ocaml.janestreet.com/ocaml-core/latest/doc/async_unix/Async_unix/Log/index.html>
Sapristi then replied
─────────────────────
I have never used Async, so I didn't know about that module. It
seems
quite close to what I had in mind, and provides most of what
easy_logging does, and much more.
Instead of instantiating modules (like Log.Global) as so called
logging singletons, Easy_logging instantiates logger objects:
┌────
│ open Easy_logging
│ logger = Logging.make_logger "my_logger" (Some Debug) [Cli
Debug];;
│ logger#info "log_message";;
└────
This is by design, since logger objects are registered and
stored at
creation (in a Logging module), to be able to modify the log
level all
logging singletons at runtime (see [Logging module] and
[example]).
(Maybe I'll switch to modules instead of classes as logging
singletons, using first-class modules to registration, but for
now
it's a bit easier for me to go with objects).
The second difference is that a Logging module can be created by
a
functor over a module of Handlers (things to write to
stdout/files/etc), making it easy to define the handlers
according to
your needs (although Async's log defaults seems quite enough).
Anyway Async's Logging will be a great source of inspiration for
me,
thanks for pointing it out !
[Logging module]
<https://sapristi.github.io/easy_logging/easy_logging/index.html#logging>
[example]
<https://sapristi.github.io/easy_logging/easy_logging/examples.html#dyn_logger>
OCaml meetup in SF on Tuesday 3/26
══════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/ocaml-meetup-in-sf-on-tuesday-3-26/3561/1>
Brandon Kase announced
──────────────────────
Hey all! We’re hosting an OCaml/ReasonML meetup in SF on Tuesday
night
(3/26) at 6:30PM. We’ll have food, drinks, and some really
interesting
talks:
Ben — Shipping a mobile game in ReasonML is not as hard as one
might
think. This talk will go over our demo-driven approach to
developing
this game, the small technical difficulties one might encounter
and
the tough non-technical ones.
Nathan — GADTs (or Generalized Algebraic Data Types) may sound
scary
at first, but they can be an approachable and useful programming
tool,
especially for designing good APIs. In this talk, we will go
over some
examples of how GADTs can be applied to make neater, easier to
use
programming interfaces.
We’ll also have plenty of time to chat, eat, and hang out.
People of
all backgrounds / skill levels are welcome, please just RSVP
below so
we know how much food to get!
<https://www.meetup.com/sv-ocaml/events/259940442/>
Yojson 2.0.0 plans
══════════════════
Archive:
<https://discuss.ocaml.org/t/yojson-2-0-0-plans/3263/34>
Deep in this thread, Stephen Bleazard said
──────────────────────────────────────────
On a slightly different topic. I think we should re-factor
ppx_deriving_yojson into a library independent core and json
library
dependent part. Then we can create ppx_deriving_jsonm etc
without
developing the whole ppx deriver. From what I have seen this
should
be pretty staight forward. What do people think?
Anders Fugmann replied
──────────────────────
I've actually created a library[1] which does exactly that; a
ppx for
general type extraction + *drivers* which contains the specific
serialization code. Its mostly feature complete (only inline
records
and gadt's are not supported yet).
Currently, the library provides drivers for json (yojson,
ezjsonm),
yaml, msgpack and xml serialization and allows for users to
easily
create their own.
It supports the same features as ppx_deriving_yojson (incl @key,
@name
and @default attribute handling) + a few more type constructs
(e.g
nonrec types), so it can be used as a plugin replacement for
ppx_deriving_json [2].
/Anders
[1] <https://github.com/andersfugmann/ppx_protocol_conv>
[2] The generated json output only differs on ADT type
constructors
without arguments which are serialized to strings, whereas
ppx_deriving_yojson serializes these to singleton lists.
iso639 - language codes
═══════════════════════
Archive:
<https://discuss.ocaml.org/t/ann-iso639-language-codes/3565/1>
Petter A. Urkedal announced
───────────────────────────
This is a new package which provides types which enumerate human
languages and language groups according to the ISO-369 standard.
The
standard has different parts depending on whether one is dealing
with
individual and macro languages or groups and families of
languages,
whether one uses two- or three-letter codes, and some historic
quirks.
See [the project page] and the [API reference] for further
details.
This library is rather mundane, but I think it can help software
dealing with multiple languages to make sure a language code is
valid,
and to make sure different language codes for the same language
maps
to the same language. I think the API is more or less in a
final form
unless there are usability issues which need to be addressed.
[the project page] <https://github.com/paurkedal/ocaml-iso639>
[API reference]
<https://paurkedal.github.io/ocaml-iso639/iso639/Iso639/index.html>
Other OCaml News
════════════════
From the ocamlcore planet blog
──────────────────────────────
Here are links from many OCaml blogs aggregated at [OCaml
Planet].
• [MirageOS security advisory 01: netchannel 1.10.0]
[OCaml Planet] <http://ocaml.org/community/planet/>
[MirageOS security advisory 01: netchannel 1.10.0]
<https://mirage.io/blog/MSA01>
Old CWN
═══════
If you happen to miss a CWN, you can [send me a message] and
I'll mail
it to you, or go take a look at [the archive] or the [RSS feed
of the
archives].
If you also wish to receive it every week by mail, you may
subscribe
[online].
[Alan Schmitt]
[send me a message] <mailto:alan.schmitt at polytechnique.org>
[the archive] <http://alan.petitepomme.net/cwn/>
[RSS feed of the archives]
<http://alan.petitepomme.net/cwn/cwn.rss>
[online] <http://lists.idyll.org/listinfo/caml-news-weekly/>
[Alan Schmitt] <http://alan.petitepomme.net/>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.idyll.org/pipermail/caml-news-weekly/attachments/20190326/f0195c08/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 487 bytes
Desc: not available
URL: <http://lists.idyll.org/pipermail/caml-news-weekly/attachments/20190326/f0195c08/attachment-0001.pgp>
More information about the caml-news-weekly
mailing list