2

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?

AndrewGB
  • 16,126
  • 5
  • 18
  • 49
nicolas
  • 9,549
  • 3
  • 39
  • 83
  • Your question is a bit vague and to some extent asking for opinion. What do you mean that "`@@deriving map` fails"? Does it yield an error? What would be "a better way"? And what is "hard"? You also shouldn't ask for the current state of things, as that will likely be invalidated with time. This question might fit better over at https://discuss.ocaml.org. – glennsl Jan 03 '22 at 17:48
  • @glennsl it's a nested data type, so I imagine the ppx extension I am using ("ppx_deriving.map") is just not made for that. The question is broader that map : I wonder how one can avoid writing plumbing code in ocaml. I am just fishing for the obvious. (may be there are some z3 plugins to find those proofs (?) or some infrastructure to ease writing such code ?). It might be better on discuss.ocaml.org you are right. – nicolas Jan 03 '22 at 18:51

1 Answers1

2

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>
ivg
  • 34,431
  • 2
  • 35
  • 63
  • 1
    It works all right for regular data type, but fails for *nested* data types. I will check the mechanics of pox_deriving, which I guess is the blessed way for those things. – nicolas Jan 03 '22 at 19:07
  • If by nested you mean recursive data type types, then it works fine as my example shows. I just fixed your definition, which I presume is an incorrect translation from Haskell. – ivg Jan 03 '22 at 19:38
  • 2
    The original code in the question looks like a correct translation of the Haskell to me. It's nested in the sense of non-regular—it includes itself applied to a different type. – dfeuer Jan 04 '22 at 00:41
  • 1
    The original type requires polymorphic recursion for its `map`, hence the need for explicit quantification. – dfeuer Jan 04 '22 at 00:52
  • 1
    indeed. I guess the terminology is not standard. I think it's from Richard Bird (cf http://www.staff.city.ac.uk/~ross/papers/debruijn.html ) Another (presumably non standard) terminology is "truly nested" where the recursing index is at the type being defined itself (the Bush type as I recall) – nicolas Jan 04 '22 at 08:53
  • 1
    Anyway, thank you very much. I know where to look. – nicolas Jan 04 '22 at 08:58
  • 2
    ah, I see, then yes, the ppx_deriver won't be able to handle this, as you need explicit quantification, which is hard to automate (you need to know which type variable to quantify). – ivg Jan 04 '22 at 15:42