haskellocamlderivingvia

deriving implementation in OCaml


The best code is code that does not exist, and in that regard, Haskell has great support for deriving implementation (that became even better with deriving via).

{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE KindSignatures, PolyKinds#-}

import Data.Kind (Type)

data NTree (a :: Type) =
    NLeaf a
  | NNode (NTree (a,a))
      deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable)

As far as I can tell, the same in OCaml requires a bit of manual plumbing


type 'a n_tree = NLeaf of 'a | NNode of ('a * 'a) n_tree (* [@@deriving map] fails *)


let rec map_ntree : 'a 'b. 'a n_tree -> ('a -> 'b) -> 'b n_tree =
 fun t f ->
  match t with
  | NLeaf x -> NLeaf (f x)
  | NNode p -> NNode (map_ntree p (fun (l, r) -> (f l, f r)))

What's the status of these derivations in OCaml?

Is there a better way to supply automatically the corresponding proof trees as of now?

Would it be hard to make some similar more powerful deriving extension?


Solution

  • There are a few ppx derivers available in opam, try opam search ppx. As an example, you can use ppx_deriving, e.g., in the OCaml top-level,

    # #use "topfind";;
    # #require "ppx_deriving.std";;
    # type 'a n_tree = NLeaf of 'a | NNode of 'a * 'a n_tree 
      [@@deriving show, eq, ord, iter, fold, map];;
    type 'a n_tree = NLeaf of 'a | NNode of 'a * 'a n_tree
    val pp_n_tree :
      (Ppx_deriving_runtime.Format.formatter -> 'a -> Ppx_deriving_runtime.unit) ->
      Ppx_deriving_runtime.Format.formatter ->
      'a n_tree -> Ppx_deriving_runtime.unit = <fun>
    val show_n_tree :
      (Ppx_deriving_runtime.Format.formatter -> 'a -> Ppx_deriving_runtime.unit) ->
      'a n_tree -> Ppx_deriving_runtime.string = <fun>
    val equal_n_tree :
      ('a -> 'a -> Ppx_deriving_runtime.bool) ->
      'a n_tree -> 'a n_tree -> Ppx_deriving_runtime.bool = <fun>
    val compare_n_tree :
      ('a -> 'a -> Ppx_deriving_runtime.int) ->
      'a n_tree -> 'a n_tree -> Ppx_deriving_runtime.int = <fun>
    val iter_n_tree : ('a -> unit) -> 'a n_tree -> unit = <fun>
    val fold_n_tree : ('a -> 'b -> 'a) -> 'a -> 'b n_tree -> 'a = <fun>
    val map_n_tree : ('a -> 'b) -> 'a n_tree -> 'b n_tree = <fun>