From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by sympa.inria.fr (Postfix) with ESMTPS id 7ED8C82355 for ; Thu, 25 Jan 2018 16:15:09 +0100 (CET) Authentication-Results: mail3-smtp-sop.national.inria.fr; spf=None smtp.pra=gabriel.scherer@gmail.com; spf=Pass smtp.mailfrom=gabriel.scherer@gmail.com; spf=None smtp.helo=postmaster@mail-qt0-f171.google.com Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of gabriel.scherer@gmail.com) identity=pra; client-ip=209.85.216.171; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="gabriel.scherer@gmail.com"; x-sender="gabriel.scherer@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of gabriel.scherer@gmail.com designates 209.85.216.171 as permitted sender) identity=mailfrom; client-ip=209.85.216.171; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="gabriel.scherer@gmail.com"; x-sender="gabriel.scherer@gmail.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-qt0-f171.google.com) identity=helo; client-ip=209.85.216.171; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="gabriel.scherer@gmail.com"; x-sender="postmaster@mail-qt0-f171.google.com"; x-conformance=sidf_compatible IronPort-PHdr: =?us-ascii?q?9a23=3Al9R2KhBAxoOjidpHSDHbUyQJP3N1i/DPJgcQr6Af?= =?us-ascii?q?oPdwSPT4ocbcNUDSrc9gkEXOFd2Cra4c0qyO6+jJYi8p2d65qncMcZhBBVcuqP?= =?us-ascii?q?49uEgeOvODElDxN/XwbiY3T4xoXV5h+GynYwAOQJ6tL1LdrWev4jEMBx7xKRR6?= =?us-ascii?q?JvjvGo7Vks+7y/2+94fcbglUmTaxe69+IAmrpgjNq8cahpdvJLwswRXTuHtIfO?= =?us-ascii?q?pWxWJsJV2Nmhv3+9m98p1+/SlOovwt78FPX7n0cKQ+VrxYES8pM3sp683xtBnM?= =?us-ascii?q?VhWA630BWWgLiBVIAgzF7BbnXpfttybxq+Rw1DWGMcDwULs5Qiqp4bt1RxD0iS?= =?us-ascii?q?cHLz85/3/Risxsl6JQvRatqwViz4LIfI2ZMfxzdb7fc9wHX2pMRsReVyJBDI2y?= =?us-ascii?q?bIUBEvQPMvpDoobnu1cDtwGzCRWwCO7tzDJDm3/43bc90+QkCQzI3RYvEMkUsH?= =?us-ascii?q?TVstr1MLoZX/2pw6nI0zrDde1Z2S3g44XPfRAuu+qDXahxccXPzUkjDRjFgUmQ?= =?us-ascii?q?qYP7JTOayP4NvnOU7+plT+2vimonpxttrTiow8chk4/EjZ8bxFDD8CV22oc1Jd?= =?us-ascii?q?ugRUFhZd6kFJpQtyaGN4dsTMMiWWdlszs5xL0eoZO3YjQGxZA9yxPca/GLaZaE?= =?us-ascii?q?7g/iWeqLPDt1hm9pdbSijBio60eg0PfzVsys3VZKsCVFlt7Mu2gI1xPJ68iHTu?= =?us-ascii?q?Jx/l692TqTzgzT5PxILEIpmabBJJ4hxbkwlpUXsUvdBCP5hEL2jKqOekUl/Oin?= =?us-ascii?q?9fjnb634qpOAM4J4kALzP6Q0lsChHOg1MxICU3WZ9OihzLHj+Ff2QLROjv04iK?= =?us-ascii?q?nZt5XaKNwUpqGjGABVyIcj5Ai7Dzu8y9QXgXkHI0xfeB2ZlYjkIF7OIPXiAve+?= =?us-ascii?q?h1Sgiitkx/fDPrH5GJXCMmDDkKv9fbZ680NT1BA8zdVb555NDrEBIenzWlPqud?= =?us-ascii?q?zDDh45NhS0zPz9BNV80IMeQ2OPDbWDPKPcq1/brt4odsuBbYlQnT/nILAM4/rv?= =?us-ascii?q?imNxzV0QdK/s2JINYzaxGvBnJFmxYGDtnpEPCzFZkBA5SbnFgVeYUDNXL025X6?= =?us-ascii?q?8m6ytzXI2vB53CS4Trm7eB0T22BLVZY2lHDhaHFnK+JNbMYOsFdC/HepwpqTcD?= =?us-ascii?q?T7X0DtZ5jUj/5j+/8KJuK6/vwgNdsJvi0NZv4OiKzEM98DV1C4KW1GTfFjgozF?= =?us-ascii?q?NNfCc/2eVEmWI40k2KiPEqjPlRFNgV7PRMAF9jaMzsitdiAtW3YTrvO9eETFH8?= =?us-ascii?q?HIejCDA1C8stm5oAOhkkXdqliR/H0myhBLpHz7E=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0CXCgBy82lahqvYVdEMUB4BBgyDaT90J?= =?us-ascii?q?weDVoE5l1KCAgKDf4YIjToVggIKH4UcAoIPBxkHBDAYAQEBAQEBAQEBAQESAQE?= =?us-ascii?q?BCAsLCCgvgjgkAYJHAQQBIwQZARsdAQMBCwYDAgs0AwICIgERAQUBCxEGEwiKF?= =?us-ascii?q?AEDDQgQllaRHUCMFIFtGAUBHCaCZQWDYgoZJw1ZgjIBAQEHAQEBAQEBGgIGEoQ?= =?us-ascii?q?/ghWBV4Fogy6DJAsEgTeDT4JlBaQKgkiTGpQll0YUBSCBFx+CCTMaI1IygXgJg?= =?us-ascii?q?hIqH4F0QDcBjjkBAQE?= X-IPAS-Result: =?us-ascii?q?A0CXCgBy82lahqvYVdEMUB4BBgyDaT90JweDVoE5l1KCAgK?= =?us-ascii?q?Df4YIjToVggIKH4UcAoIPBxkHBDAYAQEBAQEBAQEBAQESAQEBCAsLCCgvgjgkA?= =?us-ascii?q?YJHAQQBIwQZARsdAQMBCwYDAgs0AwICIgERAQUBCxEGEwiKFAEDDQgQllaRHUC?= =?us-ascii?q?MFIFtGAUBHCaCZQWDYgoZJw1ZgjIBAQEHAQEBAQEBGgIGEoQ/ghWBV4Fogy6DJ?= =?us-ascii?q?AsEgTeDT4JlBaQKgkiTGpQll0YUBSCBFx+CCTMaI1IygXgJghIqH4F0QDcBjjk?= =?us-ascii?q?BAQE?= X-IronPort-AV: E=Sophos;i="5.46,412,1511823600"; d="scan'208,217";a="252481937" Received: from mail-qt0-f171.google.com ([209.85.216.171]) by mail3-smtp-sop.national.inria.fr with ESMTP/TLS/AES128-GCM-SHA256; 25 Jan 2018 16:15:07 +0100 Received: by mail-qt0-f171.google.com with SMTP id c2so19947070qtn.9 for ; Thu, 25 Jan 2018 07:15:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=vi+qJxDIhBu9v2E6rQ2PQthCcHFKNP7YfAiCSYX3S/4=; b=tIyGAoVPkaXwQwDyMF+iXmDcWYydlK4PBsmzVMOE1EGfE1frG8PM8vG+twBCjguzt2 DFT1w2n1WZtdZV1YYMQ0v0rCBgADzmJHPp8nMeLIaaLQlQ/cOTHrgV6ubbHidlPyW76w q4B+E//Fc8wsBceSynVhIor3uo0JvfjArqFdTICXrarR3LGikSGXTOCZ0mbT1XKuhS7O R9AEWPqHopfqaDGRmW/fK70QSDol1SE5XYQGxdN938exrvuAv7HwXVk4PgnS20L0y2jv Zvb+AJCRGraZQy92/mtX4Et9cw6mAseRhtRkhYnMfvhlg+SWhbSgob5ALJdhogeabh9h 8dWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=vi+qJxDIhBu9v2E6rQ2PQthCcHFKNP7YfAiCSYX3S/4=; b=JZX0RJaDGGJYdNZ2mjxkG9+58F7BcuDQ0b3LnQ3kqC7TFwFZO0yL8hejfdcr9Ls5DY ZzOxt68W+vsTjd42TKjlaFgCSIWj7w2B3c9ZHN8cMkYzTU6MUuoSUSpViubxwlVD0Oo+ U2smYbVT6dIScpqgoRmAjuJDnQnvMLYbhZNVsU0PVSIRniPlZd/qDMblSOmsldcjEToT JRDnkVMVwnYqogfB3wYzO0umDFHHInjFcyNe+yu9pAHmCWZlnkLHoKeczupd2ZulrI67 OaJ0KKBcLTsYEsxwFAW4RqZ5QYma5tCwMvfIr0YeOnGj50wRKo3Y1V3EiQMqshAPO9wx GCdg== X-Gm-Message-State: AKwxyteqvOMvmppZvdDiUTvgPKbqTdVosGJk2LOl/4y8wxAOQMn7TEbs ash7pkji0S5wyEkPgek6GQ3pBNzot2qefiSP9RQ= X-Google-Smtp-Source: AH8x227loZh7+vtOBDYuQO5UufG5wfuv5ZTyOwBX0+sukl8hF9eyKbG5VHCdNNg45CW0Jf6YNj4CjIaBrt4UANSwp84= X-Received: by 10.55.17.84 with SMTP id b81mr14951515qkh.185.1516893306449; Thu, 25 Jan 2018 07:15:06 -0800 (PST) MIME-Version: 1.0 Received: by 10.12.212.214 with HTTP; Thu, 25 Jan 2018 07:14:26 -0800 (PST) In-Reply-To: References: From: Gabriel Scherer Date: Thu, 25 Jan 2018 16:14:26 +0100 Message-ID: To: Jean-Marc Alliot Cc: Mailing List OCaml Content-Type: multipart/alternative; boundary="001a113b086ab1713e05639b3e40" Subject: Re: [Caml-list] In need of an ocaml guru --001a113b086ab1713e05639b3e40 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable When evaluating M3.(>>=3D) m f, the input (m) is only evaluated/called once and passed to f to give a result (tmp), before the final monadic value is returned. (This monadic value may call (tmp) several times.) When evaluating M4.(>>=3D) m f, the input (m) is only evaluated/called with= in the evaluation of the result, and it will occur as many times as this result is requested. So for example, you are trying to define a recursive function on an input of size N, and you define it as (>>=3D) (recursive-call) f, where (recursive-call) calls the function on an input of size N-1, you will typically get a computation time linear in N with M3 and exponential in N with M4 -- but it could also be constant-time if the result of ((>>=3D) (recursive-call) f) is never used. On Thu, Jan 25, 2018 at 3:04 PM, Jean-Marc Alliot wrote: > Dear Ocaml Gurus, > > I have recently hit a problem that I can't really solve by myself, > probably because I lack a good understanding of the way ocaml works really > (I am more a very long-time faithful user coming from procedural languages > than a specialist of functional languages). > > The problem that I am going to describe might look slightly far-fetched in > ocaml, however it occured in a completely natural way in a Haskell program > I was writing, and it took me quite a long time to spot it; then I > translated it in ocaml, because I am more at ease with it. > > The program is included at the bottom of this message. It is short and can > be compiled without any additional modules. > The idea is to mimick (more or less...) the behavior of monads and more > specifically of the Haskell IO monad. However, no previous knowledge of > Haskell or of monads is required. > > The program implements 4 kinds of monads that all respect the monad > signature. The most interesting implementations are Monad3 and Monad4. > > With Monad3, test has type (unit Monad3.t) which is a (unit -> unit) in > "disguise". However running the resulting program prints "false", meaning > that (fun v -> return (Printf.printf "%b\n" v)) has been executed (and the > search2 function has also been executed of course). > > Opening Monad4 instead of Monad3 gives a completely different result while > it looks to a beotian like me that Monad3 is just Monad4 with a type > constructor added... > Now "false" is not printed. And if I try now to compute (test ()) to get > the actual answer, the program runs forever (well forever might not be the > exact word but I was not patient enough to wait). > > Let's make a very simple modification. In the third line of search2, it is > easy to see that the value of acc doesn't matter as the lambda expression > it is applied to is (fun _ -> ...). So it can be replaced (you can comment > out acc and uncomment the next line) by anything such as (return false), > and this should not change the result of the program. Well, it changes at > least the behaviour... Now (test ()) is computed instantaneously and prin= ts > (correctly) false... > > I would really appreciate if someone could give me answers to the > following questions: > 1) Why the programs with Monad3 and Monad4 behave differently? > 2) Why does the program with Monad4 run apparently forever (or a very long > time)? > 3) Why changing acc by (return false) in the program with Monad4 computes > immediately the result? > > Of course, in more than 25 years of programming with caml, I have never > faced such issues. This is why I am going to stick with ocaml and forget > trying to use Haskell. However, I've spent quite a lot of time on this > already, and understanding this would make that time well spent, instead = of > lost... :-) > > Friendly > > > > (* > module Monad : > sig > type 'a t > val return : 'a -> 'a t > val ( >>=3D ) : 'a t -> ('a -> 'b t) -> 'b t > end > *) > > > module Monad =3D struct > type 'a t =3D M of 'a;; > let return x =3D M x;; > let (>>=3D) (M m) (f : ('a -> 'b t)) =3D (f m);; > end;; > > module Monad1 =3D struct > type 'a t =3D M1 of 'a Lazy.t;; > let return x =3D M1 (lazy x);; > let (>>=3D) (M1 m) (f : ('a -> 'b t)) =3D f (Lazy.force m) ;; > end;; > > module Monad2 =3D struct > type 'a t =3D M2 of (unit -> 'a);; > let return x =3D M2 (fun () -> x);; > let (>>=3D) (M2 m) (f : ('a -> 'b t)) =3D (f (m ())) ;; > end;; > > module Monad3 =3D struct > type 'a t =3D M3 of (unit -> 'a);; > let return x =3D M3 (fun () -> x);; > let (>>=3D) (M3 m) (f : ('a -> 'b t)) =3D > let (M3 tmp) =3D f (m()) in > M3 (fun () -> tmp ());; > end;; > > module Monad4 =3D struct > type 'a t =3D (unit -> 'a);; > let return x =3D (fun () -> x);; > let (>>=3D) m (f : ('a -> 'b t)) =3D fun () -> (f (m ())) ();; > end;; > > (* Use any Monad here *) > open Monad4;; > > (* Poor man's multiset *) > let rec delete x (hd::tl) =3D if x=3Dhd then tl else hd::(delete x tl);; > let insert x s =3D x::s;; > let fold f b s =3D List.fold_right f s b;; > let fromlist s =3D s ;; > > let search2 mynumbers nb =3D > let rec ins numbers acc =3D > (>>=3D) > acc > (* (return false) *) > (fun _ -> > fold > (fun x acc1 -> > let numbers2 =3D delete x numbers > in fold > (fun y acc2 -> > let numbers3 =3D delete y numbers2 > and res =3D x + y > in if res =3D nb > then (return true) > else ins (insert res numbers3) acc2) > acc1 > numbers2) > acc > numbers) in > ins mynumbers (return false);; > > let b =3D fromlist [1;2;3;4];; > > (* > Monad : val test : unit Monad.t Exec: False > Monad1: val test : unit Monad1.t Exec: False > Monad2: val test : unit Monad2.t Exec: False > Monad3: val test : unit Monad3.t Exec: False > Monad4: val test : unit -> unit Exec: ---- > *) > let test =3D > (>>=3D) > (search2 b 99999999) > (fun v -> return (Printf.printf "%b\n" v));; > > (* Only use for Monad4. > It runs forever... *) > (* > let main4 =3D test ();; > *) > > - Jean-Marc Alliot > - Centre International de Math=C3=A9matiques et d'Informatique de Toulouse > (Labex CIMI) > Directeur Adjoint > - mailto:jean-marc.alliot@irit.fr > - Web: http://www.alliot.fr/fpro.html.fr > --001a113b086ab1713e05639b3e40 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
When evaluating M3.(>>=3D) m f, the input = (m) is only evaluated/called once and passed to f to give a result (tmp), b= efore the final monadic value is returned. (This monadic value may call (tm= p) several times.)

When evaluating M4.(>>=3D) m f, the i= nput (m) is only evaluated/called within the evaluation of the result, and = it will occur as many times as this result is requested.

So fo= r example, you are trying to define a recursive function on an input of siz= e N, and you define it as (>>=3D) (recursive-call) f, where (recursiv= e-call) calls the function on an input of size N-1, you will typically get = a computation time linear in N with M3 and exponential in N with M4 -- but = it could also be constant-time if the result of ((>>=3D) (recursive-c= all) f) is never used.

On Thu, Jan 25, 2018 at 3:04 PM, Jean-Marc Alliot <jean-marc.alliot@irit.fr> wrote:
=20=20 =20=20=20=20 =20=20
Dear Ocaml Gurus,

I have recently hit a problem that I can't really solve by myself, probably because I lack a good understanding of the way ocaml works really (I am more a very long-time faithful user coming from procedural languages than a specialist of functional languages).
=C2=A0
The problem that I am going to describe might look slightly far-fetched in ocaml, however it occured in a completely natural way in a Haskell program I was writing, and it took me quite a long time to spot it; then I translated it in ocaml, because I am more at ease with it.

The program is included at the bottom of this message. It is short and can be compiled without any additional modules.
The idea is to mimick (more or less...) the behavior of monads and more specifically of the Haskell IO monad. However, no previous knowledge of Haskell or of monads is required.

The program implements 4 kinds of monads that all respect the monad signature. The most interesting implementations are Monad3 and Monad4.

With Monad3, test has type (unit Monad3.t) which is a (unit -> unit) in "disguise". However running the resulting program pr= ints "false", meaning that (fun v -> return (Printf.printf &quo= t;%b\n" v)) has been executed (and the search2 function has also been executed of course).

Opening Monad4 instead of Monad3 gives a completely different result while it looks to a beotian like me that Monad3 is just Monad4 with a type constructor added...
Now "false" is not printed. And if I try now to compute (test= ()) to get the actual answer, the program runs forever (well forever might not be the exact word but I was not patient enough to wait).

Let's make a very simple modification. In the third line of search2, it is easy to see that the value of acc doesn't matter as the lambda expression it is applied to is (fun _ -> ...). So it can be replaced (you can comment out acc and uncomment the next line) by anything such as (return false), and this should not change the result of the program. Well, it changes at least the behaviour... Now (test ()) is computed instantaneously and prints (correctly) false...

I would really appreciate if someone could give me answers to the following questions:
1) Why the programs with Monad3 and Monad4 behave differently?
2) Why does the program with Monad4 run apparently forever (or a very long time)?
3) Why changing acc by (return false) in the program with Monad4 computes immediately the result?

Of course, in more than 25 years of programming with caml, I have never faced such issues. This is why I am going to stick with ocaml and forget trying to use Haskell. However, I've spent quite a lot of time on this already, and understanding this would make that time well spent, instead of lost... :-)

Friendly



(*
module Monad :
=C2=A0 sig
=C2=A0=C2=A0=C2=A0 type 'a t
=C2=A0=C2=A0=C2=A0 val return : 'a -> 'a t
=C2=A0=C2=A0=C2=A0 val ( >>=3D ) : 'a t -> ('a -> &= #39;b t) -> 'b t
=C2=A0 end
=C2=A0*)


module Monad =3D struct
=C2=A0 type 'a t =3D M of 'a;;
=C2=A0 let return x =3D M x;;
=C2=A0 let (>>=3D) (M m) (f : ('a -> 'b t)) =3D (f m);= ;
end;;

module Monad1 =3D struct
=C2=A0 type 'a t =3D M1 of 'a Lazy.t;;
=C2=A0 let return x =3D M1 (lazy x);;
=C2=A0 let (>>=3D) (M1 m) (f : ('a -> 'b t)) =3D=C2=A0= f (Lazy.force m) ;;
end;;

module Monad2 =3D struct
=C2=A0 type 'a t =3D M2 of (unit -> 'a);;
=C2=A0 let return x =3D M2 (fun () -> x);;
=C2=A0 let (>>=3D) (M2 m) (f : ('a -> 'b t)) =3D=C2=A0= (f (m ())) ;;
end;;

module Monad3 =3D struct
=C2=A0 type 'a t =3D M3 of (unit -> 'a);;
=C2=A0 let return x =3D M3 (fun () -> x);;
=C2=A0 let (>>=3D) (M3 m) (f : ('a -> 'b t)) =3D
=C2=A0=C2=A0=C2=A0 let (M3 tmp) =3D f (m()) in
=C2=A0=C2=A0=C2=A0 M3 (fun () -> tmp ());;
end;;

module Monad4 =3D struct
=C2=A0 type 'a t =3D (unit -> 'a);;
=C2=A0 let return x =3D (fun () -> x);;
=C2=A0 let (>>=3D) m (f : ('a -> 'b t)) =3D fun () -&g= t; (f (m ())) ();;
end;;

(* Use any Monad here *)
open Monad4;;

(* Poor man's multiset *)
let rec delete x (hd::tl) =3D if x=3Dhd then tl else hd::(delete x tl);= ;
let insert x s =3D x::s;;
let fold f b s =3D List.fold_right f s b;;
let fromlist=C2=A0 s =3D s ;;

let search2 mynumbers nb =3D
=C2=A0 let rec ins numbers acc =3D
=C2=A0=C2=A0=C2=A0 (>>=3D)
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 acc
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (* (return false) *)
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (fun _ ->=C2=A0=C2=A0
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fold
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (fun x acc1 ->= ;
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 let = numbers2 =3D delete x numbers
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 in f= old
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0 (fun y acc2 ->
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 let numbers3 =3D delete y numbers2<= br> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 and res =3D x + y
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 in if res =3D nb
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 then (return true= )
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 else ins (insert = res numbers3) acc2)
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0 acc1
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0 numbers2)
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 acc
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 numbers) in
=C2=A0 ins mynumbers (return false);;

let b =3D fromlist [1;2;3;4];;

(*
Monad : val test : unit Monad.t=C2=A0=C2=A0=C2=A0=C2=A0 Exec: False
Monad1: val test : unit Monad1.t=C2=A0=C2=A0=C2=A0 Exec: False
Monad2: val test : unit Monad2.t=C2=A0=C2=A0=C2=A0 Exec: False
Monad3: val test : unit Monad3.t=C2=A0=C2=A0=C2=A0 Exec: False
Monad4: val test : unit -> unit=C2=A0=C2=A0=C2=A0=C2=A0 Exec: ---- =C2=A0*)
let test =3D
=C2=A0 (>>=3D)
=C2=A0=C2=A0=C2=A0 (search2 b 99999999)
=C2=A0=C2=A0=C2=A0 (fun v -> return (Printf.printf "%b\n" = v));;

(* Only use for Monad4.
=C2=A0=C2=A0 It runs forever... *)
(*
let main4 =3D test ();;
*)

- Jean-Marc Alliot
- Centre International de Math=C3=A9matiques et d'Inform= atique de Toulouse (Labex CIMI)
=C2=A0 Directeur Adjoint
- mailto:jean-marc.a= lliot@irit.fr
- Web:=C2=A0
htt= p://www.alliot.fr/fpro.html.fr


--001a113b086ab1713e05639b3e40--