【问题标题】:F# Create Factorial function without recursion, library functions or loopsF# 创建没有递归、库函数或循环的阶乘函数
【发布时间】:2016-05-04 06:13:58
【问题描述】:

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 关键字

【问题讨论】:

标签: f#


【解决方案1】:

具有 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))

【讨论】:

  • 您知道为什么 ruby​​ 代码可以正常工作而不会出现与 ML 风格的类型推断相同的问题吗?
  • @ChristophAlrich - Ruby 是一种动态语言,因此根本没有静态类型。这样做的优点是不需要类型注释和拆箱操作,但缺点是编译器永远不会告诉你是否对不兼容的值应用了操作(你会得到一个运行时异常)。
【解决方案2】:

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

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))

【讨论】:

  • 谢谢。但是不是重新定义rec - 有没有办法用Ruby代码来表达这个函数?如果不是,为什么不呢? (我对 FP、F# 和 Lambda Calc 非常陌生)
  • 呸——我也想将你的答案标记为正确,但我选择了一个解释为什么 F# 代码不能更好地工作的那个。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2019-08-06
  • 1970-01-01
  • 2015-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-01
  • 1970-01-01
相关资源
最近更新 更多