Compact vs full/verbose 逆 combinator/operator 在 Curry 中的定义

Compact vs full/verbose definition of the inverse combinator/operator in Curry

基于 Haskell 的 KiCS2 implementation of Curry by Wolfgang Jeltsch, A Taste of Curry 的相当有趣的 2013 介绍 post,为 inverse 组合子提供了以下定义:

inverse :: (a -> b) -> (b -> a)
inverse f y | f x =:= y = x where x free

(注意: 这会做类似 inverse (+1) 3 == 2inverse (*3) 12 == 4inverse htmlHodeToStr == parseHtmlNode 的事情,以及其他的无限难以置信的好东西,对于不熟悉库里的路人)

此外,它还提供了(非确定性)split :: [a] -> ([a], [a]) 函数的 2 个替代但等效的定义:

split :: [a] -> ([a],[a])
split list | front ++ rear =:= list = (front,rear)

split' :: [a] -> ([a],[a])
split' (xs ++ ys) = (xs,ys)

以及其他一些颇具启发性的定义,但超出了本 post.

的范围

然而,我的想法使我尝试本着 splitsplit' 的精神对 inverse 进行另一种紧凑的定义:

inverse' :: (a -> b) -> (b -> a)
inverse' f (f x) = x

另一方面,这会导致以下错误:

Undefined data constructor `f'

我的问题:为什么 Curry 将可能的函数模式 (f x) 中的 f 解释为数据构造函数,而 ++ 在(也是功能性的)模式中 (xs ++ ys) 作为函数名称?

换句话说split' (xs ++ ys) = (xs,ys)中的xsys似乎正好类似于xinverse' f (f x) = x.

或者如果与 split' 的类比不是很明显,请考虑 prefix (xs ++ _) = xsorig (1 + x) = x 等,它们都可以编译并且 运行 就好了。

P.S。与原来的 post 相比,为了让这个问题更容易理解,我稍微调整了名称和类型签名。

简单来说,f x等函数式模式的语法要求函数f是在inverse'范围内可访问的已定义函数,这就是为什么[=19] =] 有效,而 f x 无效。

这是受功能模式实施的推动。它们被转换为对原始运算符 =:<= 的调用,执行一种 "lazy" 统一(惰性,因为它可能将自由变量绑定到表达式而不是值),其中出现在模式中的变量被引入为新鲜的逻辑变量。因此,函数

f (id x) = x

转换为

f y | id x =:<= y = x  where x free

如果函数模式中的函数现在是一个变量,那么就必须猜测任意函数,这在 Curry 中是不支持的。

您现在可能会遇到 f 并不是真正的自由变量,因为它是由 inverse' 的第一个参数决定的,这确实是事实。 inverse' 的定义也使用了非线性模式的语法(因为 f 出现了两次),它的翻译用新的变量替换了重复出现的变量,然后通过严格统一统一了以前重复出现的变量。例如,

pair (x, x) = success

相当于定义

pair' (x, y) | x =:= y = success

这样您的示例就会转换为

inverse' f y | f =:= g & g x =:<= y = x where g, x free

注意,这需要函数的严格统一,目前KiCS2不支持。但是,此定义适用于 PAKCS。

然而,如果我们进一步简化这个定义,我们得到

inverse' f y | f x =:<= y = x where x free

并且此定义最终在 PAKCS 和 KiCS2 中都按预期工作。

请注意,一般不建议显式使用原始运算符 =:<=,因为它可能会将逻辑变量绑定到表达式而不是值,从而违反逻辑变量的语义(包含所有 values 某种类型,但不是表达式)。功能模式的转换确保无法观察到这种违规行为,但如果直接使用 =:<= 可能会被观察到。

最后,还有一个用于 PAKCS 和 KiCS2 的库 FunctionInversion,它提供了 invf1invf5 的函数,用于反演具有不同参数的函数。

此限制有语义上的原因(因此自动脱糖是不合理的)。从概念上讲,功能模式的语义是通过评估(通过缩小)数据术语的功能模式并用这些数据术语替换功能模式来定义的,以便它们充当标准模式。为了将这个想法用作构造性定义,需要在函数模式中使用的函数定义在 "lower level" 上,而不是包含函数模式的函数。因此,必须存在所有功能的级别映射。这在 paper on functional patterns 中有详细描述(但当前编译器未检查)。因此,函数模式中的函数变量是不允许的。

有人可能会考虑扩展它,但这超出了当前功能模式的基础。