Haskell类型类控制的返回值多态解析失败问题求解
问题原因及解决方法
核心原因
你开启ScopedTypeVariables扩展后仍编译失败的核心原因是没有使用forall关键字显式量化函数签名中的类型变量d。
默认情况下Haskell的类型变量是隐式泛化的,只有被forall显式声明的类型变量,作用域才会覆盖对应函数的整个函数体。你原有代码中favorite :: d里的d是函数体内部隐式泛化的全新类型变量,和函数签名中的类型参数d无关联,编译器无法为这个无约束的新类型变量匹配到HasFavorite实例,因此编译报错。
修复方案
- 确认文件头部已开启对应扩展:
{-# LANGUAGE ScopedTypeVariables #-}
- 修改
rant函数的签名,用forall显式量化类型变量d:
rant :: forall d. (Show d, HasFavorite d) => d -> String rant x = show x ++ " sucks. " ++ show (favorite :: d) ++ " is better."
修改后即可正常编译运行,示例调用效果如下:
> rant Monkey "Monkey sucks. Donkey is better." > rant Red "Red sucks. Blue is better."
无扩展替代方案
如果你不想开启ScopedTypeVariables扩展,也可以用标准库的asTypeOf函数绑定类型,代码如下:
rant :: (Show d, HasFavorite d) => d -> String rant x = show x ++ " sucks. " ++ show (favorite `asTypeOf` x) ++ " is better."
asTypeOf会强制返回值和第二个输入参数的类型完全一致,不需要额外扩展即可通过编译。
内容的提问来源于stack exchange,提问作者Agnishom Chattopadhyay
相关产品推荐
相关产品推荐

