Haskell中intersperse函数添加loop类型签名后编译失败问题
Haskell中intersperse内部loop函数添加类型签名后编译失败的原因及解决办法
编译失败的核心原因是类型变量的作用域冲突:主函数intersperse类型签名中的a,和内部loop函数类型签名里的a是两个完全独立的类型变量——尽管名字相同,但Haskell默认会将每个类型签名的类型变量视为局部绑定的,二者没有关联。
当你在loop的定义中使用外部变量s时,s的类型是主函数的a,但loop类型签名里的a是另一个独立类型,这就导致[s]的类型([主函数a])和loop参数a、x的类型([loop的a])无法统一,编译器因此抛出类型不匹配的错误。
解决办法
方法1:启用ScopedTypeVariables扩展
这个扩展允许内层函数的类型变量直接引用外层函数的类型变量,需要在文件顶部声明扩展,并在外层函数的类型签名中用forall显式绑定类型变量:
{-# LANGUAGE ScopedTypeVariables #-} intersperse :: forall a. a -> [[a]] -> [a] intersperse s [] = [] intersperse s (x:[]) = x intersperse s (x:xs) = loop x xs where loop :: [a] -> [[a]] -> [a] loop a [] = a loop a (x:xs) = loop (a ++ [s] ++ x) xs
方法2:移除loop的类型签名
如果不想启用扩展,直接去掉loop的类型签名即可,编译器会自动推导正确的类型:
intersperse :: a -> [[a]] -> [a] intersperse s [] = [] intersperse s (x:[]) = x intersperse s (x:xs) = loop x xs where loop a [] = a loop a (x:xs) = loop (a ++ [s] ++ x) xs
内容的提问来源于stack exchange,提问作者ehsun7b
相关产品推荐
相关产品推荐

