let intersect
    ~(run_with:Machine.t)
    ?(configuration=Configuration.Intersect.default)
    ~primary ~intersect_with output
  =
  let open KEDSL in
  let bedtools = Machine.get_tool run_with Machine.Tool.Default.bedtools in
  let arguments =
    (sprintf "-a %s" (Filename.quote primary#product#path)) ^
    (List.map ~f:(fun n -> (Filename.quote n#product#path)) intersect_with
     |> String.concat ~sep:","
     |> sprintf " -b %s ")
    ^ (Configuration.Intersect.render configuration)
  in
  let program =
    Program.(Machine.Tool.(init bedtools)
             && sh ("bedtools intersect "
                    ^ arguments ^ " > " ^ output)) in
  let name = sprintf "bedtools-intersect-%s-with-%s"
      (Filename.basename primary#product#path)
      (String.concat ~sep:"__"
         (List.map
            ~f:(fun n -> (Filename.basename n#product#path)) intersect_with)) in
  let make = Machine.run_program run_with ~name program in
  let edges = [
    depends_on primary;
    depends_on Machine.Tool.(ensure bedtools);
    on_failure_activate (Remove.file run_with output)
  ] @ (List.map ~f:depends_on intersect_with) in
  let host = Machine.as_host run_with in
  let out = single_file ~host output in
  workflow_node out ~name ~edges ~make
    ~done_when:(`Is_verified (out#is_bigger_than 1))