From mboxrd@z Thu Jan 1 00:00:00 1970 From: ludo@gnu.org (Ludovic =?utf-8?Q?Court=C3=A8s?=) Subject: The store monad Date: Tue, 01 Oct 2013 23:49:54 +0200 Message-ID: <87r4c4acfx.fsf@gnu.org> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:57931) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VR7uJ-0005Wk-2B for guix-devel@gnu.org; Tue, 01 Oct 2013 17:55:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VR7uE-0004cm-7U for guix-devel@gnu.org; Tue, 01 Oct 2013 17:55:02 -0400 Received: from hera.aquilenet.fr ([141.255.128.1]:49797) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VR7uE-0004ch-17 for guix-devel@gnu.org; Tue, 01 Oct 2013 17:54:58 -0400 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id AE6521634 for ; Tue, 1 Oct 2013 23:49:55 +0200 (CEST) Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id AdZ750pAgtiY for ; Tue, 1 Oct 2013 23:49:55 +0200 (CEST) Received: from pluto (reverse-83.fdn.fr [80.67.176.83]) by hera.aquilenet.fr (Postfix) with ESMTPSA id 5DF4F136B for ; Tue, 1 Oct 2013 23:49:55 +0200 (CEST) List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org To: guix-devel@gnu.org Hi! I just pushed the =E2=80=98wip-monad=E2=80=99 branch for review (like we do= in Guile, =E2=80=98wip-=E2=80=99 means that I may rebase it until it=E2=80=99s comple= te.) So far in Guix we had two things: store primitives from (guix store) that explicitly manipulate the store via effectful RPCs, and package definitions, which are abstract, inert, and never see a store object. Package objects are great, but they=E2=80=99re not necessarily suitable for small derivations like the many we have in (gnu system =E2=80=A6) modules. = Yet, it would be nicer if functions in those modules did not have to explicitly carry a =E2=80=98store=E2=80=99 parameter, and if the sequence o= f store operations could be built and hidden under the carpet. This is where monads come in. In addition to being fashionable in FP circles ;-), they offer a nice way to do exactly that: to add context to values (here, the context is the store), and to build sequences of computations. So now, instead of writing procedures that explicitly manipulate the store: (define (foo store) (let* ((drv (package-derivation store bash)) (out (derivation->output-path drv))) (add-text-to-store store "foo.sh" (format #f "#!~a/bin/sh echo hello world" out)))) ;; Call the function: (foo (open-connection)) we can now write a monadic function: (define (foo) (mlet the-store-monad ((sh (package-file bash "bin/sh"))) (text-file "foo.sh" (string-append "#!" sh "\necho hello world")))) ;; Call the monadic function, and =E2=80=9Crun=E2=80=9D its monadic resul= t: ((foo) (open-connection)) Notice how =E2=80=98store=E2=80=99 completely disappeared. Here we use =E2= =80=98mlet=E2=80=99, not =E2=80=98let=E2=80=99, because =E2=80=98package-file=E2=80=99 returns a =E2= =80=9Cmonadic value=E2=80=9D instead of a normal value. Monadic values in the store monad are currently just (lambda (store) =E2=80= =A6). That=E2=80=99s the first time I use monads after just reading about it. Th= is was mostly inspired by and . A good introduction is at . Actually, values in the Nix programming language essentially live in the store monad, even if that=E2=80=99s not what it=E2=80=99s called. I plan to polish it, add tests, and merge it in the coming days or so. Comments welcome! Thanks, Ludo=E2=80=99.