(** {1 Basic definitions} *)type('a, 'b) sum = Leftof'a | Rightof'b(** An element of [('a, 'b) sum] is either a ['a] or a ['b] *)type'a stream = Streamof(unit -> ('a * 'a stream) option)(** (possibly infinite) streams of values *)(** you have to implement the functions below; this may not be veryuseful for the rest of the project, but consider this a warmupexercize *)valnil : 'a streamvalcons : 'a -> 'a stream -> 'a stream(** lazy cons *)vallcons : 'a -> (unit -> 'a stream) -> 'a streamvalget : 'a stream -> ('a * 'a stream) optionvaltake : 'a stream -> int -> 'a listvalnumber_stream : int stream(** the infinite stream [0,1,2,3...] *)valstream_of_list : 'a list -> 'a stream(** {1 First part: fair search}The goal of the module Logic1, whose signature is below, is torepresent search problems: an OCaml expression of type ['a search]represents a description of values of type ['a] that we would liketo search for. For example, with the combinators of this moduleyou can define a value of type [(int * int) search] that searchesfor a couple of prime numbers [(p,q)] such that [q = p+2] or, ifyou want, that represent all such couples.In the general case, such search problems may have zero, severalor even an infinite number of solutions. You will have toimplement a function{[solve : int -> 'a search -> 'a list]}such that [solve n prob] returns a list of [n] solutions to thesearch problem [prob], or less if there do not exist so enoughsolutions. Solutions may be returned in any order, but you must beale to provide all possible solutions (if there is a finite numberof solutions).*)moduleLogic1 :sigtype'a search(** the type of search descriptions *)valsolve : int -> 'a search -> 'a list(** [solve n prob] returns [n] solutions to the search problem[prob], or less if there aren't so many solutions *)valstream : 'a stream -> 'a search(** a stream can be seen as a search problems whose solutions areall the elements present in the stream *)valreturn : 'a -> 'a search(** a single value also defines a search problem (which hasexactly this value as solution *)valfail : 'a search(** the search problem with no solution *)valmap : ('a -> 'b) -> 'a search -> 'b search(** the solutions of [map f prob] are all the [f x] such that [x]is a solution of [prob]. *)valsum : 'a search -> 'b search -> ('a, 'b) sum search(** the solutions of [sum pa pb] are all the solutions of problem[pa], and all the solutions of problem [pb] *)valprod : 'a search -> 'b search -> ('a * 'b) searchvalguard : ('a -> bool) -> 'a search -> 'a search(** the solutions of [guard condition prob] are the solutions of[prob] that also satisfy [condition]. *)end(** EvaluationThe following code should work:{[let () =let open Logic1 inlet number = stream number_stream inlet posnum = guard (fun n -> n > 0) number inlet pytha =(* we search for triples pythagorean triples (a, b, c):a² + b² = c²to avoid duplication of solutions, we also request (a < b) *)let ab =prod posnum posnum|> guard (fun (a,b) -> a < b) inprod ab posnum|> guard (fun ((a,b),c) -> a*a+b*b=c*c) insolve 10 pytha |> List.iter(fun ((a,b),c) -> Printf.printf "%d² + %d² = %d²\n" a b c)]}A difficulty with this exercize is that [posnumber] has aninfinite number of solutions. If you haven't defined [prod]carefully enough, this program may loop without returninganything, despite having simple solutions.PS: (|>) and (@@) are infix operators defined in OCaml 4.01 aslet (@@) f x = f xlet (|>) x f = f xIf you have an older OCaml version, just define themat the top of your file.*)(** {1 Second part: distribution probabilities}*)