Haskell代码出现类型注解错误,无法理解无穷类型与类型不匹配问题
错误原因排查与修复
一、初始版本无穷类型错误解释
你初始版本的核心问题是multiApp的类型签名定义错误,引发类型冲突导致无穷类型报错:
- 你给
multiApp第一个参数定义的类型是(a -> a),意思是接收一个a类型值返回a类型值 - 但实际逻辑里这个参数
f要接收的是multiAppi返回的[a]类型列表,导致编译器推断类型时出现矛盾:- 从
f $ multiAppi gs x可得:multiAppi的返回值必须是a类型(要匹配f的入参类型) - 从
multiAppi的实现((head gs) x) : multiAppi (tail gs) x可得:(:)运算符要求右操作数是左操作数类型的列表,即multiAppi的返回值必须是[a]类型 - 上述两个推导要求
a ~ [a],这是不可能成立的无穷类型(a等于a的列表,无限套娃),所以编译器抛出了occurs check错误。
- 从
二、修改后版本报错解释
你修改后的版本已经修正了multiApp第一个参数的类型,但是仍然存在一个限制:你把函数列表里的函数类型限定为a -> a,要求函数返回值类型和输入x的类型完全一致。
你新的测试用例multiApp (sum::[Int]->Int) [head, last] [1::Int,2,3,4]中:
- 输入
x的类型是[Int] - 你传入的
head、last函数类型是[Int] -> Int,不符合a -> a的要求(a是[Int],返回值是Int不是[Int]),所以编译器抛出类型不匹配错误。
三、最终修复代码
把函数签名泛化,允许函数列表的返回值和输入x类型不同即可:
-- f接收[b]类型的结果列表,返回c类型 -- 函数列表每个元素接收a类型的x,返回b类型 -- 整体输入a类型的x,返回c类型 multiApp :: ([b] -> c) -> [a -> b] -> a -> c multiApp f gs x = f $ multiAppi gs x -- 把每个函数应用到x上,返回结果列表 multiAppi :: [a -> b] -> a -> [b] multiAppi [] x = [] multiAppi (g:gs) x = g x : multiAppi gs x
四、验证测试用例
所有你给出的示例都可以正常运行:
multiApp id [] 7返回[]multiApp id [id, reverse, tail] "This is a test"返回["This is a test","tset a si sihT","his is a test"]multiApp sum [(1+), (^3), (+2)] 1返回6multiApp (sum :: [Int] -> Int) [head, last] [1::Int,2,3,4]返回5
内容的提问来源于stack exchange,提问作者Juha R
相关产品推荐
相关产品推荐

