module OrderEntry = struct
include Showable
type t = {securityId: string ; price: int ; qty: int ; } [@@deriving show]
end
module PriceBook(S: SideType) =
struct
type t = { id: string ; price: int ; side: string ; mutable price_map: OrderEntry.t list } [@@deriving show] ;;
let init_book p = { id = "0001" ; price = p ; side = "BID" ; price_map = [] }
end;;
module SellPriceBook = PriceBook(struct let side = Sell end)
let pb = SellPriceBook.init_book
let () = show pb
File "bin/main.ml", line 8, characters 9-13:
8 | let () = show pb
^^^^
Error: Unbound value show
What am missing to be able to print the content of the types ?
let pb = SellPriceBook.init_book 42 (* was missing a price *)
let str = SellPriceBook.show pb (* was missing the module *)
let () = print_endline str (* show returns a string, not unit *)
To clarify, the PPX automatically defines the show function for your type next to it, in the module SellPriceBook. The show function is not defined globally which is why you got the unbound error
You should also be able to drop the ppx_show.runtime from your dune file (as you are actually using ppx_deriving.show and not ppx_show)
Thanks for the comment and pointing out my mistakes.
I have tried the suggestion, and it is still complaining.
File "bin/main.ml", line 8, characters 10-28:
8 | let str = SellPriceBook.show pb (* was missing the module *)
^^^^^^^^^^^^^^^^^^
Error: Unbound value SellPriceBook.show
It would make sense that the function is generated under the module where the derived type is. But for some reason its not binding to the module ?
Do you have a signature on the functor PriceBook in the real code? (or an .mli file?) The show function must be exported if you want to use it from the outside (you can also add the [@@deriving show] in the signature/mli near the type t)
(Ah, and in case your code is split between a library and an executable, you also need the (preprocess (pps ppx_deriving.show etc)) in the library dune file, not only on the final executable)
Main.ml
open! Base
open Orderbook
module SellPriceBook = PriceBook(struct let side = Sell end)
let pb = SellPriceBook.init_book 42 (* was missing a price *)
let str = SellPriceBook.show pb (* was missing the module *)
let () = print_endline str (* show returns a string, not unit *)
orderbook.ml
open Base
open Core
type side = Buy | Sell [@@deriving show]
module type SideType = sig
val side : side
end
module OrderEntry = struct
type t = {securityId: string ; price: int ; qty: int ; } [@@deriving show]
end
module PriceBook(S: SideType) =
struct
type price_book_level = { id: string ; price: int ; side: string ; mutable price_map: OrderEntry.t list } [@@deriving show] ;;
let init_book p = { id = "0001" ; price = p ; side = "BID" ; price_map = [] }
let to_string pb = Sexp.to_string pb
end;;
Finding it very strange why it doesnt want to bind
But it doesnt answer whether it works for classes in Ocaml? On another hand, is there any incentive to use classes/objects in Ocaml or its better to stick to fully functional approach?
Sorry, I realize that my post isn’t directly talking about printing in OCaml programs. I’ll update it. The context here is that once you’ve defined a pretty-printer, you can use the Format module to print it e.g.
let pp_obj = ...
let obj = object ... end
Format.printf "this is the object: %a\n" pp_obj obj
My post shows an example of defining a pretty-printer for an object.
(Side note: objects in OCaml can be fully functional. For better or worse, OCaml offers lots of non-redundant ways to structure programs and implement abstractions, that all fit together subdividing the design space. What differentiates objects from records is subtyping: one object type will be a special case of another object type if it offers more methods. Not so for records: when one record has strictly more fields than another, it cannot be used in place of the other.)