let rec to_file_prefix:
  type a.
  ?read:[ `R1 of string | `R2 of string ] ->
  a t -> string =
  fun ?read w ->
    begin match w with
    | With_metadata (_, p) -> to_file_prefix ?read p
    | Fastq_gz _ -> failwith "TODO"
    | Fastq _ -> failwith "TODO"
    | Single_end_sample (info, _) -> info.fragment_id
    | Gunzip_concat [] -> failwith "TODO"
    | Gunzip_concat (_ :: _) ->
      begin match read with
      | None -> "-cat"
      | Some (`R1 s) -> sprintf "%s-R1-cat" s
      | Some (`R2 s) -> sprintf "%s-R2-cat" s
      end
    | Concat_text _ -> failwith "TODO"
    | Bam_sample (name, _) -> Filename.basename name
    | Bam_to_fastq (_, how, bam) ->
      sprintf "%s-b2fq-%s"
        (to_file_prefix bam)
        (match how with `Paired -> "PE" | `Single -> "SE")
    | Paired_end_sample (info, _ , _) -> info.fragment_id
    | Bwa (configuration, sample) ->
      sprintf "%s-bwa-%s"
        (to_file_prefix sample) (Bwa.Configuration.Aln.name configuration)
    | Bwa_mem (configuration, sample) ->
      sprintf "%s-bwa-mem-%s"
        (to_file_prefix sample) (Bwa.Configuration.Mem.name configuration)
    | Star (configuration, sample) ->
      sprintf "%s-%s-star-aligned"
        (to_file_prefix sample)
        (Star.Configuration.Align.name configuration)
    | Hisat (conf, sample) ->
      sprintf "%s-hisat-%s-aligned" (to_file_prefix sample) (conf.Hisat.Configuration.name)
    | Stringtie (conf, sample) ->
      sprintf "%s-%s-stringtie"
        (to_file_prefix sample)
        (conf.Stringtie.Configuration.name)
    | Mosaik (sample) ->
      sprintf "%s-mosaik" (to_file_prefix sample)
    | Gatk_indel_realigner ((indel_cfg, target_cfg), bam) ->
      let open Gatk.Configuration in
      sprintf "%s-indelrealigned-%s-%s"
        (to_file_prefix ?read bam)
        indel_cfg.Indel_realigner.name
        target_cfg.Realigner_target_creator.name
    | Gatk_bqsr ((bqsr_cfg, print_reads_cfg), bam) ->
      let open Gatk.Configuration in
      sprintf "%s-bqsr-%s-%s"
        (to_file_prefix ?read bam)
        bqsr_cfg.Bqsr.name
        print_reads_cfg.Print_reads.name
    | Picard_mark_duplicates (_, bam) ->
      (* The settings, for now, do not impact the result *)
      sprintf "%s-dedup" (to_file_prefix ?read bam)
    | Bam_pair (nor, tum) -> to_file_prefix tum
    | Somatic_variant_caller (vc, bp) ->
      let prev = to_file_prefix bp in
      sprintf "%s-%s-%s" prev
        vc.Variant_caller.name
        vc.Variant_caller.configuration_name
    | Germline_variant_caller (vc, bp) ->
      let prev = to_file_prefix bp in
      sprintf "%s-%s-%s" prev
        vc.Variant_caller.name
        vc.Variant_caller.configuration_name
    | Seq2HLA s ->
      sprintf "seq2hla-%s" (to_file_prefix ?read s)
    | Optitype (kind, s) ->
      sprintf "optitype-%s-%s"
        (match kind with `DNA -> "DNA" | `RNA -> "RNA")
        (to_file_prefix ?read s)
    end