Haskell类型检查失败:如何让getBasis与foo的类型参数a一致
问题解决方法
你的问题出在Haskell类型推断的作用域上——默认情况下,函数签名里的类型变量a和函数体中注解的a是两个不相关的变量,类型检查器无法将它们关联起来。以下是两种可行的解决方案:
方法一:启用ScopedTypeVariables扩展
这个扩展允许函数签名中的类型变量在函数体内被引用,从而明确绑定类型。
修改后的代码:
{-# LANGUAGE ScopedTypeVariables #-} class Basis a where getBasis :: Int -> [a] foo :: forall a b. (Basis a) => Int -> (a -> b) -> IO () foo n f = do let theBasis = getBasis n :: [a] -- 现在可以正常使用f处理theBasis,比如 map f theBasis undefined
关键改动:
- 顶部添加
{-# LANGUAGE ScopedTypeVariables #-}启用扩展 - 函数签名前加上
forall a b.,让a和b的作用域覆盖整个函数体 - 此时
[a]注解里的a会和签名中的a完全匹配
方法二:启用TypeApplications扩展
通过类型应用语法直接指定getBasis的类型参数,不需要额外的类型注解。
修改后的代码:
{-# LANGUAGE TypeApplications #-} class Basis a where getBasis :: Int -> [a] foo :: (Basis a) => Int -> (a -> b) -> IO () foo n f = do let theBasis = getBasis @a n -- 同样可以正常使用f处理theBasis undefined
这里@a明确告诉getBasis要使用的类型就是foo签名中约束的a,类型检查器会直接匹配两者。
内容的提问来源于stack exchange,提问作者Anthony D'Arienzo
相关产品推荐
相关产品推荐

