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

Haskell函数组合点符号使用疑问:如何改写sum(map square [1..n])

Haskell函数组合(点符号)的错误原因与正确用法

先看你现有的正确代码:

平方函数:

square :: Integer -> Integer
square x = x * x

用括号实现的求和平方函数:

sumsquares :: Integer -> Integer
sumsquares n = sum (map square [1..n])

错误写法的问题分析

  1. sum . map square [1..n] 报错原因
    函数组合运算符(.)的作用是组合两个函数,它的类型是(b -> c) -> (a -> b) -> a -> c——要求左右两边都是函数,且前一个函数的输出类型能匹配后一个的输入类型。
    而map square [1..n]已经是一个具体的列表值(不是函数),sum是[Integer] -> Integer类型的函数,你试图把函数和值组合,完全不符合(.)的使用规则,所以报错。

  2. sum . square map [1..n] 报错原因
    这个写法的结构和类型完全混乱:square的参数需要是Integer类型,但你把map(一个函数)传给它,类型不匹配;同时[1..n]的位置也不对,整个表达式既不符合函数组合逻辑,也不符合函数调用规则,必然报错。

正确的点符号使用方式

函数组合的核心是组合函数而非值,所以需要把[1..n]转换成一个接受n作为参数的函数,再和其他函数组合。

无点风格(Point-free)写法

sumsquares :: Integer -> Integer
sumsquares = sum . map square . enumFromTo 1

解释:

  • enumFromTo 1 是一个Integer -> [Integer]类型的函数,作用是接受参数n,生成列表[1..n]
  • map square 是[Integer] -> [Integer]类型的函数,对列表每个元素平方
  • sum 是[Integer] -> Integer类型的函数,对列表求和
    这三个函数的输入输出类型依次匹配,用(.)组合后,就得到了一个Integer -> Integer类型的函数,和sumsquares的类型完全一致。

保留参数的写法(结合$避免括号,注意这不是函数组合)

如果你想保留参数n,可以用函数应用运算符$来替代括号,写法是:

sumsquares :: Integer -> Integer
sumsquares n = sum $ map square [1..n]

$的作用是降低右边表达式的优先级,让右边先执行,和括号写法等价,但这不属于函数组合的范畴,只是简化括号的技巧。

内容的提问来源于stack exchange,提问作者Alex Kay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 09:45:41