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

Haskell中Data.Function.on有何作用?求示例及高效应用场景

Haskell中on函数的用法示例与场景

on是Data.Function模块里的工具函数,核心作用是把一个二元函数“包装”后,让它先对两个输入执行同一个转换操作,再用原二元函数处理转换后的结果。它的类型签名和等价实现很直白:

on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
on op f x y = op (f x) (f y)

基础使用示例

1. 按属性比较/排序

比如对字符串列表按长度排序,不用on的话需要写冗余的lambda,用on能直接把逻辑拆解开:

import Data.Function (on)
import Data.List (sortBy)

-- 按字符串长度从长到短排序
sortByLengthDesc :: [String] -> [String]
sortByLengthDesc = sortBy (compare `on` length)

这里compare on length完全等价于\x y -> compare (length x) (length y),但代码更简洁直观。

再比如处理自定义类型,按用户的年龄字段比较:

data User = User { name :: String, age :: Int } deriving (Show)

-- 判断两个用户年龄是否相同
sameAge :: User -> User -> Bool
sameAge = (==) `on` age

-- 按年龄升序排序用户列表
sortUsersByAge :: [User] -> [User]
sortUsersByAge = sortBy (compare `on` age)

2. 数值运算的包装

比如计算两个数的绝对值之和,用on可以避免重复写abs:

absSum :: Int -> Int -> Int
absSum = (+) `on` abs
-- 等价于 \x y -> abs x + abs y

让代码更简洁的场景案例

1. 分组操作

把列表元素按某个属性分组时,on能大幅简化lambda:

import Data.List (groupBy)

-- 按字符串长度分组
groupByLength :: [String] -> [[String]]
groupByLength = groupBy ((==) `on` length)

不用on的话需要写groupBy (\x y -> length x == length y),重复的length调用显得冗余。

2. 元组的属性排序

对元组列表按第二个元素排序,on配合snd能让代码更简洁:

-- 按元组的第二个元素升序排序
sortBySecond :: Ord b => [(a, b)] -> [(a, b)]
sortBySecond = sortBy (compare `on` snd)

如果不用on,得写sortBy (\(x1,y1) (x2,y2) -> compare y1 y2),不仅代码更长,还容易写错元组索引。

3. 复杂转换的复用

当转换逻辑比较复杂时,on能让你只定义一次转换函数,再复用在不同的二元操作上:

-- 提取字符串的第一个字符(处理空字符串的情况)
firstChar :: String -> Char
firstChar [] = '_'
firstChar (c:_) = c

-- 判断两个字符串首字符是否相同
sameFirstChar :: String -> String -> Bool
sameFirstChar = (==) `on` firstChar

-- 按首字符的字典序排序
sortByFirstChar :: [String] -> [String]
sortByFirstChar = sortBy (compare `on` firstChar)

为什么on实用?

  • 减少重复代码:避免在lambda里重复写相同的转换逻辑,尤其是转换函数复杂时,只需要定义一次。
  • 提高可读性:代码意图更清晰——先明确要做什么转换,再明确要执行什么二元操作,结构一目了然。
  • 贴合函数式风格:用函数组合代替冗余lambda,更符合Haskell的函数式编程思想。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 15:43:24