SML中来自元组的“Curry”

时间:2018-03-06 05:57:49

标签: functional-programming sml mosml

我正在尝试定义一个函数包装器,用于解决SML中的元组。

fun curry f = fn (x, y) z => f x y z;

给我错误

  

非标识符应用于模式。

我是ML新手,不知道为什么fn中的模式匹配不起作用。

我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:6)

  

我正在尝试定义一个函数包装器,用于解决SML中的元组。

fun curry f = fn (x, y) z => f x y z;
     

我怎样才能做到这一点?

SML中的闭包不允许多个参数,但您可以替换它们。

curry通常做的是接受通常接受元组f的函数(x, y),而是返回一个修改后的函数,该函数分别使用xy 。以下是一些定义curry的等效方法:

fun curry f x y = f (x, y)
fun curry f x = fn y => f (x, y)
fun curry f = fn x => fn y => f (x, y)
val curry = fn f => fn x => fn y => f (x, y)

相反,uncurry取而代之的是一个f函数,它分别取xy并返回一个带(x, y)的修改函数。这是写uncurry的一种方法:

fun uncurry f (x, y) = f x y

很容易混淆两者。

修复您编写的函数以便编译的一种方法是插入额外的=> fn

fun what_is_this f = fn (x, y) => fn z => f x y z
                            (* ^- there *)

在给它命名之前,让我们分析它的作用。它有类型签名:

fn : ('a -> 'b -> 'c -> 'd) -> 'a * 'b -> 'c -> 'd
                  (* now a tuple -^    ^- still curried *)

意味着它需要三个curried参数(xyz)的函数,并返回一个修改过的函数,其中前两个参数现在位于元组中(uncurried)而第三个仍然是咖喱。这实际上是 uncurry 的不太通用的版本。更清晰的写作方式是:

fun what_is_this f (x, y) z = f x y z

如果对三个参数的函数使用uncurry,则会产生相同的效果,但是对于具有两个curried参数的任何内容,都不能使用what_is_this。所以我要说这是uncurry的一个不太有用的变体。

然而,curry / uncurry还有其他更有用的变体。例如,您可以制作uncurry_twicef x y z转换为(uncurry_twice f) ((x, y), z),或uncurry3f x y z转换为(uncurry3 f) (x, y, z)

fun uncurry_twice f = uncurry (uncurry f)
fun uncurry3 f (x, y, z) = f x y z