struct

    type t = [
      | `separator of char
      | `strict_about of [ `row_length | `cell_type ]
      | `format of item_type array
    ] list
    with sexp

    let separators tags =
      List.filter_map tags (function
        | `separator c -> Some c
        | _ -> None)

    let strict_row_length tags =
      List.exists tags (function `strict_about `row_length -> true | _ -> false)

    let strict_cell_type tags =
      List.exists tags (function `strict_about `cell_type -> true | _ -> false)

    let format tags =
      List.find_map tags (function `format f -> Some f | _ -> None)

    let default = [ `separator '\t' ]

    let default_extension tags =
      match separators tags with
      | '\t' :: _ -> "tsv"
      | ',' :: _ -> "csv"
      | _ -> "table"

    let to_string t = sexp_of_t t |> Sexplib.Sexp.to_string
    let of_string s =
      try Ok (Sexplib.Sexp.of_string s |> t_of_sexp)
      with e -> module_error (`tags_of_string e)

  end