# How do I pass Eio 'env'?

**URL:** https://discuss.ocaml.org/t/how-do-i-pass-eio-env/17003
**Category:** Learning
**Created:** [July 23, 2025, 3:52pm UTC](https://discuss.ocaml.org/t/how-do-i-pass-eio-env/17003 "2025-07-23T15:52:08Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![Mohan\_Radhakrishnan](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mohan_radhakrishnan/32/1905_2.png) [@Mohan\_Radhakrishnan](https://discuss.ocaml.org/u/Mohan_Radhakrishnan)
#### Post date: [July 23, 2025, 3:52pm UTC](https://discuss.ocaml.org/t/how-do-i-pass-eio-env/17003/1 "2025-07-23T15:52:08Z")

</div>

Hello,

The following code works if I create a file first. The directory permissions are proper. And I also noticed there are two `Eio_main.run ` . I believe there should only be one. So I tried to pass `env ` by declaring it in the `sig` but the type looks odd. So I am wondering now about how to pass `env` around.

Am I using the pattern wrongly ?

```auto
module type WalWriter =
sig
  val write : bytes -> unit
  val read : unit->string
end

```

```auto
module WalWriter = struct

let write (data : bytes) =
  let ( / ) = Eio.Path.( / ) in
    Eio_main.run @@ fun env ->
      let path = Eio.Stdenv.fs env in
      let p = path / "/Users"/"anu"/"Documents"/"rays"/"Bitcask"/"bitcask"/"bitcask.log" in
      Eio.Path.with_open_out ~append:true ~create:(`If_missing 0o600) p (fun f ->
      try
          let bytes_written =
           Eio.Flow.single_write f [Cstruct.of_bytes
                                                 data]
          in Printf.printf "%d bytes written" bytes_written
     with
       | ex -> traceln "%a" Eio.Exn.pp ex
     )

let read ()=
let ( / ) = Eio.Path.( / ) in
 Eio_main.run @@ fun env ->
  let path = Eio.Stdenv.fs env in
  let p = path / "/Users"/"anu"/"Documents"/"rays"/"Bitcask"/"bitcask"/"bitcask.log" in
  let lines =
  if (Sys.file_exists "/Users/anu/Documents/rays/Bitcask/bitcask/bitcask.log") then
   Eio.Path.load p
  else
     raise Not_found
  in lines

end

```

Update :

```auto
module type WalWriter =
sig
  val write : bytes -> Eio_unix.Stdenv.base -> unit
  val read : unit -> Eio_unix.Stdenv.base -> string
end

```

This compiles and I have removed the redundant `Eio_main.run`

Thanks.

---

<div class="post-metadata">

### Author: ![patricoferris](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/patricoferris/32/3621_2.png) [@patricoferris](https://discuss.ocaml.org/u/patricoferris)
#### Post date: [July 23, 2025, 4:50pm UTC](https://discuss.ocaml.org/t/how-do-i-pass-eio-env/17003/2 "2025-07-23T16:50:10Z")

</div>

Hi @Mohan_Radhakrishnan,

Looks like you got it sorted for your particular example.

I will add that one of the main ideas behind Eio is to pass in only those things that your function needs. The standard environment contains a host of things (like process spawning, network access etc.) that perhaps your functions do not need. It seems your `WalWriter` modules may only need access to the filesystem capability, in which case you could change the API to be:

```ocaml
module type WalWriter =
sig
  val write : bytes -> _ Eio.Path.t -> unit
  val read : unit -> _ Eio.Path.t -> string
end

```

Now, from an Eio point of view, these functions are hopefully not doing anything with the other capabilities!

You can read more about this [in the documentation](https://github.com/ocaml-multicore/eio?tab=readme-ov-file#design-note-capabilities) and also [on @talex5’s blog post](https://roscidus.com/blog/blog/2023/04/26/lambda-capabilities/). Note that if “pulling out” the capabilities is too cumbersome and/or passing in multiple arguments is not desirable you can always use subtyping too :))

---

<div class="post-metadata">

### Author: ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)
#### Post date: [July 23, 2025, 5:15pm UTC](https://discuss.ocaml.org/t/how-do-i-pass-eio-env/17003/3 "2025-07-23T17:15:33Z")

</div>

I think a more typical signature would be:

```auto
module type WalWriter = sig
  val path : _ Eio.Path.t
  val write : bytes -> unit
  val read : unit -> string
end

```

Then for the implementation you’d have to do:

```auto
let ( / ) = Eio.Path.( / )

let main env =
  ...
  let module Impl = struct
    let path = Eio.Stdenv.fs env / ...

    let write data = Eio.Path.with_open_out ... path ...

    let read () =
      ... Eio.Path.load path ...
  end
  in
  ...

```

Alternatively, you could make a functor to pass the path in to the module:

```auto
module MakeWalWriter(P : sig val path : _ Eio.Path.t end) = struct
  let write data = Eio.Path.with_open_out ... P.path ...

  let read () =
    ... Eio.Path.load P.path ...
end

```
