如何实现支持类型校验的F#函数组合器?对比C#实现差异
需求:实现类型匹配的F#函数组合器
需要编写一个Composer类的Compose方法,能够校验传入的两个函数类型:当第一个函数的输出类型与第二个函数的输入类型匹配时,返回组合后的函数(Some(f >> g));否则返回None。
示例代码
let f (i : int) : string = i.ToString() let g (s : string) : char[] = s.ToCharArray() // 期望返回 Some (f >> g) let foo = Composer().Compose(f,g) // 期望返回 None let bar = Composer().Compose(g,f)
尝试的两种失败实现
1. 强制转换的暴力实现(运行时不允许)
这种实现试图通过类型判断后强制转换函数,但F#不允许此类运行时强制转换,无法工作:
type Composer() = member _.Compose<'a,'b,'c,'d> (f : 'a -> 'b,g : 'c -> 'd) : ('a -> 'd) option = match typeof<'b> = typeof<'c> with | true -> let g1 : 'b -> 'd = // 运行时强制转换不被允许 // 部分类型不支持运行时类型测试 fun b -> g (b :?> 'c) Some (f >> g1) | false -> None
2. 类型测试实现(编译报错)
尝试直接对函数做类型测试,但编译时报错:
type Composer() = member _.Compose<'a,'b,'c,'d> (f : 'a -> 'b,g : 'c -> 'd) : ('a -> 'd) option = if (g :? ('b -> 'd)) then Some (f >> (g :?> ('b -> 'd))) else None
错误信息:
the type 'c -> 'd does not have any proper subtypes and cannot be used as the source of a type test or runtime coercion
困惑点
按逻辑,类型本身应该是自身的子类型,但F#类型系统却提示仅接受“合适子类型”。而对应的C#实现却能正常工作,符合预期。
可行的C#实现
static Func<A,D>? Compose<A,B,C,D>(Func<A,B> f,Func<C,D> g) { var g1 = g as Func<B, D>; if (g1 == null) { return null; } else { return (A a) => g1(f(a)); } } [Fact] public void ComposeTest() { Func<int,int> f = x => x + 1; Func<int, string> g = x => x.ToString(); var foo = Compose(f,g); var bar = Compose(g,f); foo(1); }
寻求解决方案
需要实现符合需求的F#函数组合器。
内容的提问来源于stack exchange,提问作者MrD at KookerellaLtd
相关产品推荐
相关产品推荐

