Haskell中为参数化类型特定类型参数实现类型类的问题
解决方案
首先明确问题根源:
- 第一个实例报错是因为Haskell默认的实例声明规则要求实例类型必须是
T a1...an的形式(所有参数为类型变量),而ParametricType HoldsString中HoldsString是具体类型,违反了该规则。 - 第二个实例报错是因为实例中的类型变量
a是“刚性”的,必须覆盖所有可能的类型,但你只处理了HoldsString的情况,编译器无法接受这种不完整的定义。
下面提供两种可行实现方式:
方式一:启用FlexibleInstances扩展
GHC的FlexibleInstances扩展允许实例类型参数使用具体类型,直接解决第一个报错问题。只需在代码开头添加扩展声明,保留你最初的实例定义即可:
{-# LANGUAGE FlexibleInstances #-} data ParametricType a = TypeConstructor a class GetsString a where getString :: a -> String data HoldsString = HoldsString String instance GetsString (ParametricType HoldsString) where getString (TypeConstructor (HoldsString str)) = str
方式二:给参数类型添加约束(符合Haskell 98标准)
如果不想依赖扩展,可以先给HoldsString本身实例化GetsString,再给ParametricType定义一个带约束的通用实例——只要参数类型a实现了GetsString,ParametricType a就自动拥有该实例:
data ParametricType a = TypeConstructor a class GetsString a where getString :: a -> String data HoldsString = HoldsString String instance GetsString HoldsString where getString (HoldsString str) = str instance GetsString a => GetsString (ParametricType a) where getString (TypeConstructor x) = getString x
这种方式更通用,后续如果有其他类型需要通过ParametricType获取字符串,只需给该类型添加GetsString实例即可,无需修改ParametricType的实例代码。
内容的提问来源于stack exchange,提问作者Chris J Harris
相关产品推荐
相关产品推荐

