You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用bs-deriving自定义特定类型实例?以Bar的show十六进制输出为例

在bs-deriving中自定义特定类型的Show实例

刚好我之前也遇到过类似的需求,其实核心思路很简单:对需要自定义格式的类型手动实现show函数,其他依赖它的类型依然可以正常用[@deriving show]自动派生,因为bs-deriving在生成show逻辑时,会自动查找对应类型已有的show函数。

直接拿你的示例来改:

方法1:完全手动实现目标类型的show

如果bar类型的所有构造函数都需要自定义格式,我们可以跳过它的[@deriving show],自己写show_bar函数:

// 先定义bar类型,不自动派生show
type bar = | Bar(int)

// 手动实现show_bar,把整数转成十六进制格式
let show_bar = function
  | Bar(n) -> Printf.sprintf "Bar(0x%x)" n

// foo类型依然用[@deriving show],它会自动调用我们的show_bar处理bar类型
[@deriving show] type foo = | Foo(int, bar)

测试一下效果:

let demo = Foo(42, Bar(255))
print_endline (show_foo demo)
// 输出:Foo(42, Bar(0xff))

方法2:部分自定义(保留其他构造函数的默认格式)

如果bar有多个构造函数,只想自定义其中一个,比如新增一个Baz(string)构造函数,想保留它的默认show格式,我们可以先让[@deriving show]生成默认函数,再覆盖需要修改的部分:

// 先用[@deriving show]生成默认的show_bar
[@deriving show] type bar = | Bar(int) | Baz(string)

// 先保存默认生成的show函数,避免被覆盖后丢失
let default_show_bar = show_bar

// 重写show_bar,只自定义Bar的格式,Baz用默认逻辑
let show_bar = function
  | Bar(n) -> Printf.sprintf "Bar(0x%x)" n
  | other -> default_show_bar other

// foo依然自动派生
[@deriving show] type foo = | Foo(int, bar)

测试效果:

let demo1 = Bar(16)
print_endline (show_bar demo1) // 输出:Bar(0x10)

let demo2 = Baz("hello")
print_endline (show_bar demo2) // 输出:Baz("hello")

let demo3 = Foo(123, Bar(255))
print_endline (show_foo demo3) // 输出:Foo(123, Bar(0xff))

原理说明

bs-deriving生成的show函数(比如show_foo),会对类型中的每个字段调用对应类型的show函数:

  • 对于内置类型(int、string等)用默认的show_int、show_string;
  • 对于自定义类型(比如bar),会查找名为show_bar的函数——不管这个函数是自动派生的还是你手动写的,都会优先使用已定义的版本。

这样我们就可以灵活地只修改需要自定义的类型,其他类型依然享受自动派生的便利。

内容的提问来源于stack exchange,提问作者Felix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 11:08:15