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

如何在F#中定义三元内联运算符|>>及通用运算符|>>*?

F# 自定义中缀运算符|>>的优先级问题与解决方案

需求概述

  • 定义中缀运算符|>>,使i |>> f1 f2等价于(f1 i, f2 i),将参数传递给两个函数并返回结果元组
  • 定义通用绑定运算符|>>*,使i (|>>* b) f1 f2等价于b (f1 i) (f2 i),支持自定义结果绑定逻辑

现有尝试代码

let (|>>*) (i: 'IN) (b : 'S -> 'T -> 'OUT) =
    fun (f1: 'IN -> 'S) (f2: 'IN -> 'T) ->
        b (f1 i) (f2 i)
        
let (|>>) i f1  =
    (|>>*) i (fun a b -> a,b) f1
        
let x =
    10 |>> (fun x -> x + 2) (fun x -> x + 2)

问题分析

直接调用10 |>> f1 f2会触发类型解析错误,必须写成(10 |>> f1) f2才能得到正确结果。根源在于F#中函数调用(空格分隔)的优先级远高于自定义中缀运算符:

  • 函数应用的优先级为10(最高级别),所有自定义中缀运算符默认优先级为4,最高仅能设置为9,无法超过函数应用的优先级
  • 因此10 |>> f1 f2会被解析为10 |>> (f1 f2),即把f2作为参数传给f1,而非预期的将f1和f2依次传递给|>>的返回函数,导致类型不匹配

解决方案

方案1:调整运算符定义,直接接受元组形式的函数对

这种方案类型安全,语法直观,仅需给函数对添加括号:

// 通用绑定运算符 |>>* 改为直接接受两个函数参数
let (|>>*) (i: 'IN) (b : 'S -> 'T -> 'OUT) (f1: 'IN -> 'S) (f2: 'IN -> 'T) =
    b (f1 i) (f2 i)

// 元组版本的 |>> 运算符
let (|>>) i (f1, f2) =
    (|>>*) i (fun a b -> a, b) f1 f2

// 调用示例
let x = 10 |>> (fun x -> x + 2, fun x -> x - 1) // 返回 (12, 9)

方案2:保持柯里化设计,使用括号或管道符明确调用顺序

如果坚持原有的柯里化逻辑,需通过括号或管道符强制指定解析顺序:

// 保留原运算符定义,添加优先级和结合性属性优化解析
[<OperatorPrecedence(9)>]
[<RightAssociative>]
let (|>>*) (i: 'IN) (b : 'S -> 'T -> 'OUT) =
    fun (f1: 'IN -> 'S) (f2: 'IN -> 'T) ->
        b (f1 i) (f2 i)
        
[<OperatorPrecedence(9)>]
[<RightAssociative>]
let (|>>) i f1  =
    (|>>*) i (fun a b -> a,b) f1

// 调用方式1:添加括号明确顺序
let x1 = (10 |>> (fun x -> x + 2)) (fun x -> x - 1) // 返回 (12, 9)

// 调用方式2:使用管道符传递第二个函数
let x2 = 10 |>> (fun x -> x + 2) |> (fun f -> f (fun x -> x - 1))

方案3:新增组合运算符,接近预期语法

通过新增一个函数组合运算符&&&,实现无需括号的调用语法:

// 函数组合运算符:将两个函数组合为返回元组的函数
let (&&&) f1 f2 = fun i -> (f1 i, f2 i)

// 管道运算符:将参数传递给组合后的函数
let (|>>) i f = f i

// 调用示例:语法接近预期的 `i |>> f1 f2`
let x = 10 |>> (fun x -> x + 2) &&& (fun x -> x - 1) // 返回 (12, 9)

关键结论

F#的语法规则决定了函数应用的优先级无法被任何运算符超越,因此无法直接实现i |>> f1 f2的解析逻辑。上述方案可根据实际需求选择,其中方案3的语法最接近预期,方案1的类型安全性最优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 08:53:11