【问题标题】:"Curry" from tuple in SML来自 SML 元组的“咖喱”
【发布时间】:2018-08-13 22:10:00
【问题描述】:

我正在尝试定义一个函数包装器,用于在 SML 中对一个元组进行curry。

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

给我错误

应用于模式的非标识符。

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

我怎样才能做到这一点?

【问题讨论】:

  • 匿名函数只能带一个参数。 z 在那里做什么?
  • 另外,柯里化通常意味着将函数从a * b -> c 转换为a -> b -> c,而不是从a -> b -> c -> d 转换为a * b -> c -> d

标签: functional-programming sml mosml


【解决方案1】:

我正在尝试定义一个函数包装器,用于在 SML 中对一个元组进行curry。

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

这意味着它接受三个咖喱参数(xyz)的函数并返回一个修改后的函数,其中前两个参数现在在一个元组中(未咖喱),第三个仍然是咖喱.这实际上是一个不太通用的 uncurry 版本。更清晰的写法是:

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

如果你对一个有三个参数的函数使用uncurry,你会得到同样的效果,但是你不能对任何有两个咖喱参数的函数使用what_is_this。所以我想说这是uncurry 的一个不太有用的变体。

不过,curry/uncurry 还有其他更有用的变体。例如,您可以创建一个将f x y z 转换为(uncurry_twice f) ((x, y), z)uncurry_twice,或者一个将f x y z 转换为(uncurry3 f) (x, y, z)uncurry3

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

【讨论】:

  • 你把这么多的爱放在了这里!谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-02
  • 1970-01-01
  • 2018-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多