如何使用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
相关产品推荐
相关产品推荐

