Haskell中如何为Double包装类型Coordinate实现Semigroup实例
报错原因
- 核心问题是类型定义与实例声明的「种类(Kind,可简单理解为类型的类型)」不匹配:你当前的
Coordinate定义是无类型参数的具体类型,要注意Haskell内置的双精度浮点类型名首字母必须大写,正确的基础定义为data Coordinate = Coordinate Double,该类型的kind为*,代表它本身就是可以直接使用的具体类型。 - 你编写的实例声明
Semigroup (Coordinate a)默认将Coordinate当成了需要接收一个类型参数的类型构造器,要求它的kind为* -> *,和实际定义的kind冲突,因此类型检查器抛出匹配错误。 - 附加的遗漏点:基于数值相加实现Semigroup时,需要对应包装的类型有
Num类约束,你原来的实例声明没有补充该约束。
正确实现
根据你的需求可以选择两种实现方式:
场景1:Coordinate固定包装Double,不需要泛型
直接使用无参数的类型定义即可:
data Coordinate = Coordinate Double
实例声明不需要加额外的类型参数,因为Coordinate本身就是符合Semigroup参数要求的具体类型:
instance Semigroup Coordinate where Coordinate a <> Coordinate b = Coordinate (a + b)
Double本身已经实现了Num类,不需要额外加约束即可直接相加。
场景2:需要Coordinate作为泛型包装器,适配任意数值类型
先修改类型定义,为它补充类型参数:
data Coordinate a = Coordinate a
此时Coordinate的kind为* -> *,符合带参数的实例声明要求,补充Num约束即可:
instance Num a => Semigroup (Coordinate a) where Coordinate a <> Coordinate b = Coordinate (a + b)
该实现可以兼容Int、Integer、Double等所有实现了Num类的数值类型。
内容的提问来源于stack exchange,提问作者daikonradish
相关产品推荐
相关产品推荐

