如何定义包含Eq、Ord、Show约束的类型构造器以避免重复编写?
解决重复约束的方法
你原来尝试的EqOrdShow类型别名写法行不通——这种把约束和类型构造器绑定的方式不符合Haskell的类型别名规则,还会引发循环引用问题(比如Foo n t = EqOrdShow Foo n t会无限展开)。正确的思路是用约束同义词,把重复的约束组打包成可复用的名称:
1. 定义约束同义词
直接将需要的一组约束打包成新的约束名称,两种写法可选:
-- 直接打包两个类型变量的Eq/Ord/Show约束 type EqOrdShow n t = (Eq n, Eq t, Ord n, Ord t, Show n, Show t) -- 更模块化的写法:先定义单个类型的约束,再组合 type SingleEqOrdShow a = (Eq a, Ord a, Show a) type EqOrdShow n t = (SingleEqOrdShow n, SingleEqOrdShow t)
2. 在类型别名中使用
原来的Foo类型定义可以简化为:
type Foo n t = EqOrdShow n t => Bar n t
3. 在GADT构造器中使用
对于Baz的GADT定义,直接在构造器的约束位置替换成约束同义词即可:
data Baz n t where Baz :: EqOrdShow n t => { f1 :: !n, f2 :: !t } -> Baz n t
4. 在函数中使用
函数的类型签名也能直接复用这个约束同义词,比如:
printBaz :: EqOrdShow n t => Baz n t -> IO () printBaz (Baz x y) = print (x, y)
这样就能彻底避免重复编写冗长的约束列表了。
内容的提问来源于stack exchange,提问作者Todd O'Bryan
相关产品推荐
相关产品推荐

