You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell中含列表构造器的`a`和类型为何不匹配`a`的列表?

解决原始递归组合函数的类型不匹配问题

你的核心问题是没有把普通列表包装成PrimT类型,导致编译器无法匹配函数f的参数类型。让我一步步拆解:

错误原因分析

看你定义的o函数类型:

o :: PrimT (PrimT b -> PrimT c) -> PrimT (PrimT a -> PrimT b) -> PrimT a -> PrimT c

其中Sgl f里的f类型是PrimT b -> PrimT c——它要求传入一个PrimT b类型的值(要么是Sgl包裹的单个值,要么是Sqc包裹的列表)。但你写的[g args | g <- gs]生成的是普通Haskell列表[PrimT b],并没有用PrimT的构造器包裹,这俩类型完全不兼容,编译器自然报错。

修正后的代码

针对你设计的四个组合场景,我们只需要把生成的结果用对应的PrimT构造器包装即可:

o :: PrimT (PrimT b -> PrimT c) -> PrimT (PrimT a -> PrimT b) -> PrimT a -> PrimT c
-- 场景1:单个函数 + 函数列表 + 参数列表
o (Sgl f) (Sqc gs) (Sqc args) = f $ Sqc [g args | g <- gs]
-- 场景2:单个函数 + 函数列表 + 单个参数
o (Sgl f) (Sqc gs) (Sgl arg) = f $ Sqc [g arg | g <- gs]
-- 场景3:单个函数 + 单个函数 + 参数列表
o (Sgl f) (Sgl g) (Sqc args) = f $ g args
-- 场景4:单个函数 + 单个函数 + 单个参数
o (Sgl f) (Sgl g) (Sgl arg) = f $ g arg

关键细节说明

  • 对于函数列表的场景(1、2):多个g的执行结果会被收集成普通列表,我们用Sqc把它包裹成PrimT b类型,这样才能满足f的参数要求。
  • 对于单个函数的场景(3、4):g的执行结果本身就是PrimT b类型,直接传给f即可,不需要额外包装。

另外提一句:你的zero和pi返回的是Either String Int,但nu返回的是PrimT Int,这里类型有点不一致,后续可能需要统一成Either String (PrimT Int)来处理错误情况,不过这是另一个优化方向了。

内容的提问来源于stack exchange,提问作者lo tolmencre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:54:20