Recursion SML中的递归匿名函数
可以在SML中编写递归匿名函数吗?我知道我可以用Recursion SML中的递归匿名函数,recursion,functional-programming,anonymous-function,sml,Recursion,Functional Programming,Anonymous Function,Sml,可以在SML中编写递归匿名函数吗?我知道我可以用fun语法,但我很好奇 作为我想要的一个例子,我写了: val fact = fn n => case n of 0 => 1 | x => x * fact (n - 1) 您只需将rec放在val之后,如中所示 val rec fact = fn n => case n of 0 =>
fun
语法,但我很好奇
作为我想要的一个例子,我写了:
val fact =
fn n => case n of
0 => 1
| x => x * fact (n - 1)
您只需将
rec
放在val
之后,如中所示
val rec fact =
fn n => case n of
0 => 1
| x => x * fact (n - 1)
在第一节顶部附近介绍了这一点。当您将匿名函数绑定到 变量因为
val rec
只是fun
的派生形式,没有
除了外观上的不同,你还可以用
fun
语法。您还可以在fn
表达式中进行模式匹配
如案例
,案例源自fn
因此,简单地说,您可以将函数编写为
val rec fact = fn 0 => 1
| x => x * fact (x - 1)
但这与下面的内容完全相同,更具可读性(在我的观点中)
在我看来,使用
longval rec
,这是因为您可以使用
注释和强制类型。例如,如果您在和之前看过Haskell代码
就像他们输入注释函数的方式一样,你可以写一些东西
像这样
val rec fact : int -> int =
fn 0 => 1
| x => x * fact (x - 1)
正如templatetypedef提到的,可以使用定点
组合器。这样的组合器可能看起来像
fun Y f =
let
exception BlackHole
val r = ref (fn _ => raise BlackHole)
fun a x = !r x
fun ta f = (r := f ; f)
in
ta (f a)
end
然后,您可以使用下面的代码计算fact 5
,该代码使用匿名
函数来表示函数,然后绑定
计算到res
val res =
Y (fn fact =>
fn 0 => 1
| n => n * fact (n - 1)
)
5
定点代码和示例计算由Morten Brøns Pedersen提供
对George Kangas回答的最新回应:
在我所知道的语言中,递归函数总是绑定到 名称方便和常规的方法是通过关键字提供的,如 “定义”或“let”或“letrec” 从定义上来说,这是微不足道的事实。如果函数(递归或非递归)没有绑定到名称,那么它将是匿名的 非传统的、更匿名的方式是lambda绑定 我看不出匿名函数有什么不寻常的地方,它们一直在SML中使用,事实上在任何函数语言中都是如此。它甚至开始出现在越来越多的命令式语言中 Jesper Reenberg的回答显示了lambda绑定;“匿名者” 函数通过lambdas(调用 SML中的“fn”) 匿名函数实际上是匿名的(不是“匿名的”--没有引号),是的,它当然会被绑定在作为参数传递到的任何函数的范围内。在任何其他情况下,这种语言都是毫无用处的。调用
map(fnx=>x)[…]
时也会发生同样的情况,在本例中,匿名标识函数实际上仍然是匿名的
匿名函数的“正常”定义(至少根据)表示它不能绑定到标识符,这有点弱,应该包含“在当前环境中”的隐式语句
事实上,对于我的示例来说,这是正确的,在一个仅包含funy…
和val res…
val Y: (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b
val res: int32
由此可以看出,环境中没有绑定任何匿名函数
较短的“lambdanonymous”替代方案,需要启动OCaml
通过“ocaml-矩形”:
你似乎完全误解了原来问题的意思:
可以在SML中编写递归匿名函数吗
答案很简单,是的。复杂的答案是(除其他外?)一个使用定点组合器的例子,而不是一个“lambdanonymous”(什么意思)的例子,在另一种语言中使用SML中甚至不可能实现的功能。在我知道的语言中,递归函数总是绑定到一个名称。“定义”或“let”或“letrec”等关键字提供了方便而常规的方法 非传统的、更匿名的方式是lambda绑定。Jesper Reenberg的回答显示了lambda绑定;“匿名”函数通过lambdas(在SML中称为“fn”)绑定到名称“f”和“fact” 一个较短的“lambdanonymous”替代方案,需要由“OCaml-rectypes”启动OCaml: 哪个生产7个!=5040
let fun fact 0 = 1
| fact x = x * fact (x - 1)
in
fact
end
这是一个递归匿名函数。“事实”这个名称只在内部使用
有些语言(如Coq)使用“fix”作为递归函数的基元,而有些语言(如SML)使用recursive let作为基元。这两个原语可以相互编码:
fix f => e
:= let rec f = e in f end
let rec f = e ... in ... end
:= let f = fix f => e ... in ... end
我不是ML方面的专家,但您可能正在寻找涉及定点组合器的东西,如Y组合器,这是从匿名函数构建递归函数的典型方法。@templatetypedef只要您不想使用匿名函数,您就是正确的(请记住,原来的问题不使用匿名函数),但是这不是一种很好的方法。请参阅我答案的最后一部分以获取示例:)明白了。我想维基百科没有这些信息,所以我到处找,除了那里。谢谢。非常感谢!:)你真是个救命恩人!:)你读过密码了吗?用OCaml示例回答这个问题并没有给原始问题带来价值,特别是当使用SML没有的递归类型时。总而言之,除了陈述一些已经知道的事实,我看不出你文章的意义。查看我的最新帖子。“[…]因为val rec只是乐趣的衍生形式[…]”:这不是相反吗?不。也许我们的意思是一样的,但从两个不同的角度来看
val rec
是核心语言的一部分,而fun
关键字是派生形式。我不知道
(fun f n -> f f n)
(fun f n -> if n = 0 then 1 else n * (f f (n - 1))
7;;
let fun fact 0 = 1
| fact x = x * fact (x - 1)
in
fact
end
fix f => e
:= let rec f = e in f end
let rec f = e ... in ... end
:= let f = fix f => e ... in ... end