在 OCaml 中推导实现

deriving implementation in OCaml

最好的代码是不存在的代码,在这方面,Haskell 对派生实现有很好的支持(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)

据我所知,OCaml 中的相同内容需要一些手动管道


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)))

这些推导在 OCaml 中的状态如何?

现在有没有更好的方法自动提供相应的证明树?

做一些类似的更强大的 deriving 扩展会不会很困难?

opam 中有一些可用的 ppx 派生器,试试 opam search ppx。例如,您可以使用 ppx_deriving,例如,在 OCaml 顶层,

# #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>