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

Haskell多参数函数如何使用eta reduce进行简化?

多参数函数的Eta归约问题

问题背景

在完成fp-course的练习时,遇到了多参数函数无法直接用普通函数组合符.进行Eta归约的问题:

  • 正确实现的replicateA:
replicateA n ka = sequence $ replicate n ka

尝试写成replicateA = sequence . replicate时无法运行。

  • 类似的flatMap例子:
flatMap f xs = flatten $ map f xs

写成flatMap = flatten . map同样报错。

问题原因

普通的函数组合符.的类型是(b -> c) -> (a -> b) -> a -> c,它只能组合单参数函数。而replicate和map都是双参数的柯里化函数,直接用.组合时,参数的应用顺序和函数类型无法匹配:

  • replicate的类型是Int -> a -> [a],sequence的类型是Applicative f => [f a] -> f [a],sequence . replicate的类型会变成Int -> (a -> [f a]) -> f [a],和目标的Int -> f a -> f [a]不符。
  • map的类型是(a -> b) -> [a] -> [b],flatten的类型是[[b]] -> [b],flatten . map的类型是(a -> b) -> ([a] -> [b]),但map f返回的是[[b]],直接组合时参数层级不匹配。

解决方法

针对多参数函数的Eta归约,需要使用嵌套的函数组合,通过.的嵌套来处理多参数的柯里化结构:

1. 处理replicateA

可以写成:

replicateA = (sequence .) . replicate

这里(sequence .)是将sequence包装成一个接受单参数函数的组合器,再和replicate组合,最终类型匹配Int -> f a -> f [a]。

2. 处理flatMap

同理,flatMap可以写成:

flatMap = (flatten .) . map

(flatten .)包装flatten后,和双参数的map组合,得到符合要求的(a -> [b]) -> [a] -> [b]类型。

另一种写法:自定义双参数组合符

你也可以自定义一个专门处理双参数函数的组合符,让写法更直观:

(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
(.:) f g x y = f (g x y)

之后就可以这样写:

replicateA = sequence .: replicate
flatMap = flatten .: map

内容的提问来源于stack exchange,提问作者zichao liu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 15:46:00