F#创建因子函数,不带递归,库函数或循环

时间:2016-05-03 21:35:25

标签: f#

video about functional programming 35:14,Jim Weirich编写了一个函数来计算阶乘,而不使用递归,库函数或循环: see image of Ruby code here

Ruby中的代码

fx = ->(improver) {
  improver.(improver)
}.(
   ->(improver) {
     ->(n) { n.zero ? 1 : n * improver.(improver).(n-1) }
   }
   )

我试图表达这种方法F#

let fx =
    (fun improver -> improver(improver))(
    fun improver ->
             fun n ->
             if n = 0 then 1
             else n * improver(improver(n - 1)))

我目前被困在

类型不匹配。期待'a但给定'a - > “B
统一''a'和''a - >时,结果类型将是无限的。 'B'

我似乎无法找到正确的类型注释或表达函数的其他方式

编辑:

*没有 rec 关键字

2 个答案:

答案 0 :(得分:5)

ML样式类型推断的语言将无法推断出术语fun improver -> improver improver的类型;他们首先假设lambda定义的类型为'a -> 'b(对于某些未确定类型'a'b),因此参数improver的类型为'a ,但随后它应用于自身以提供结果('b类型),因此improver必须同时具有类型'a -> 'b。但是在F#类型系统中,没有办法统一这些类型(在简单类型的lambda演算中,根本没有办法给这个术语一个类型)。 My answer您在评论中链接到的问题涵盖了一些变通方法。 @desco已经提供了其中一个。另一个是:

let fx = (fun (improver:obj->_) -> improver improver)
         (fun improver n -> 
              if n = 0 then 1 
              else n * (improver :?> _) improver (n-1))

答案 1 :(得分:3)

这是作弊,但你可以使用类型

type Self<'T> = delegate of Self<'T> -> 'T
let fx1 = (fun (x: Self<_>) -> x.Invoke(x))(Self(fun x -> fun n -> if n = 0 then 1 else x.Invoke(x)(n - 1) * n))

type Rec<'T> = Rec of (Rec<'T> -> 'T)
let fx2 = (fun (Rec(f ) as r) -> f r)(Rec(fun ((Rec f) as r) -> fun n -> if n = 0 then 1 else f(r)(n - 1) * n))