如何消除重复函数并为不同类型实现Binary实例?
解决重复函数的方案
完全可以移除这些重复的函数!核心思路是把通用逻辑提取成多态辅助函数,让两个Binary实例共享同一段代码,不用为不同类型写重复实现。
具体实现思路
1. 提取通用函数消除重复
假设你的yes和yes'、..>和~.>逻辑完全一致,只是类型签名适配不同的数据类型,那可以先把核心逻辑抽成多态的通用版本:
-- 通用版yes逻辑 yesGeneric :: Binary b => ... -> b yesGeneric = -- 这里写原来yes/yes'的核心实现 -- 通用版组合操作符逻辑 genericCombine :: Binary a => ... -> ... -> ... genericCombine x y = -- 原来..>/~.>的核心实现
然后在两个Binary实例里直接复用这些通用函数:
instance Binary TypeA where put = ... yesGeneric ... genericCombine ... get = ... yesGeneric ... genericCombine ... instance Binary TypeB where put = ... yesGeneric ... genericCombine ... get = ... yesGeneric ... genericCombine ...
2. 用自定义类型类进一步抽象
如果你的两个类型序列化逻辑高度相似,还可以定义一个专属类型类,把业务相关的序列化逻辑抽离出来,再基于它实现Binary实例:
class MySerializable a where serialize :: a -> Put deserialize :: Get a -- 为两个类型实现自定义序列化逻辑 instance MySerializable TypeA where serialize = -- 通用序列化逻辑 deserialize = -- 通用反序列化逻辑 instance MySerializable TypeB where serialize = -- 通用序列化逻辑(和TypeA一致的话可以写默认实现) deserialize = -- 通用反序列化逻辑 -- Binary实例只做一层转发,彻底消除重复 instance Binary TypeA where put = serialize get = deserialize instance Binary TypeB where put = serialize get = deserialize
3. 用DerivingVia简化实例定义(GHC 8.6+)
如果用的是较新的GHC版本,还可以借助DerivingVia扩展,通过通用newtype包装来共享实例:
{-# LANGUAGE DerivingVia #-} newtype GenericBinary a = GenericBinary a instance MySerializable a => Binary (GenericBinary a) where put (GenericBinary x) = serialize x get = GenericBinary <$> deserialize -- 直接通过DerivingVia复用通用实现 data TypeA = ... deriving (Binary) via (GenericBinary TypeA) data TypeB = ... deriving (Binary) via (GenericBinary TypeB)
关键总结
- 核心是抽离通用逻辑,避免为不同类型写重复的序列化/反序列化代码
- 多态函数、自定义类型类、
DerivingVia都是消除重复的有效手段,可根据你的代码复杂度选择合适的方式
内容的提问来源于stack exchange,提问作者BlackCap
相关产品推荐
相关产品推荐

