Haskell:自定义两两交换列表函数中为何不能用last替代tail?
Haskell pairExchange函数替换tail为last的类型错误原因
核心原因是类型不匹配触发了无限类型推导错误,具体分析如下:
- 首先明确相关操作/函数的类型签名:
- 列表构造符
(:)的类型为a -> [a] -> [a],要求左侧为单个元素,右侧为同类型元素构成的列表,最终返回新列表 tail :: [a] -> [a]:返回列表去掉首元素后的子列表last :: [a] -> a:返回列表的最后一个元素
- 列表构造符
- 原代码
otherwise分支的类型合法性:
原分支代码为head xs : x : tail xs:- 函数声明返回值为
[a],x的类型为a,xs的类型为[a] tail xs返回类型为[a],符合(:)右参数的要求,因此x : tail xs的类型为[a]- 最外层
head xs(类型a)与x : tail xs(类型[a])通过(:)连接后返回[a],和函数声明的返回类型完全匹配
- 函数声明返回值为
- 替换为
last xs后的错误逻辑:
替换后分支代码为head xs : x : last xs:last xs的返回类型为a,而(:)要求右参数必须是[a]类型,编译器会尝试推导让a等价于[a]以满足类型要求,这是不可能实现的无限类型,因此抛出对应报错。
- 认知偏差修正:
当xs长度为2时,tail xs的结果是单元素列表,例如xs = [2,3]时tail xs = [3];而last xs的结果是单个元素,对应值为3,二者类型、值均不相同,不能直接替换。如果要使用last实现相同逻辑,需要将其包裹为单元素列表,写为head xs : x : [last xs]即可通过编译。
内容的提问来源于stack exchange,提问作者Zimanz
相关产品推荐
相关产品推荐

