Search code examples
typesocamlincompatibility

Incompatible typeclasses with primitive types


I wasn't sure how to word this question for a useful Google search so I was hoping that you guys could help me. I'm using the OCaml Sqlite3 library. It has a user-defined data type that looks like

module Data = struct
  type t =
    | NONE
    | NULL
    | INT of int64
    | FLOAT of float
    | TEXT of string
    | BLOB of string

I'm trying to follow the tutorial at:

http://www.mega-nerd.com/erikd/Blog/CodeHacking/Ocaml/snip_sqlite.html. Specifically, I try to run the function

let create_tables db =
      (* Create two tables in the database. *)
      let tables =
      [    "people", "pkey INTEGER PRIMARY KEY, first TEXT, last TEXT, age INTEGER" ;
      "cars", "pkey INTEGER PRIMARY KEY, make TEXT, model TEXT" ;
      ]
  in
  let make_table (name, layout) =
      let stmt = Printf.sprintf "CREATE TABLE %s (%s);" name layout in
      match Sqlite3.exec db stmt with
      |    Sqlite3.Rc.OK -> Printf.printf "Table '%s' created.\n" name
      |    x -> raise (E (Sqlite3.Rc.to_string x))
  in
  List.iter make_table tables

The problem I'm having is when I try to use the file in utop I get

Error: This expression has type string * string but an expression was expected of type Data.t * Data.t. Type string is not compatible with type Data.t

Which doesn't make sense because string should be coerced to a Data.t, shouldn't it? What am I not understanding here?

Thank you!

EDIT: It seems like the way to solve this is

Data.TEXT "my text query stuff here"

This seems ugly though. Creating a list of these explicitly looks like

let tables =
      [ Data.TEXT "people", Data.TEXT "pkey INTEGER PRIMARY KEY, first TEXT, last TEXT, age INTEGER" ;
      Data.TEXT "cars", Data.TEXT "pkey INTEGER PRIMARY KEY, make TEXT, model TEXT" ;
      ]

Is there a more idiomatic way to handle this?


Solution

  • You can define your own conversion function from pairs of strings to pairs of Data.t:

    let todt (a, b) = (Data.TEXT a, Data.TEXT b)
    

    Then you can say

    List.map todt tables
    

    (Using the original definition of tables as a list of pairs of strings.)