Curry中逆组合器/运算符的紧凑与完全/详细定义

时间:2015-11-04 15:42:06

标签: pattern-matching logic-programming curry functional-logic-progr kics2

Wolfgang Jeltsch KiCS2对Haskell基于Curry实施A Taste of Curry的2013年相当引人入胜的帖子提供了inverse组合子的以下定义:

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

注意:这会做inverse (+1) 3 == 2inverse (*3) 12 == 4以及inverse htmlHodeToStr == parseHtmlNode之类的事情,以及无数令人难以置信的令人难以置信的事情,对于路人来说不熟悉咖喱)

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

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

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

以及其他一些颇具启发性的定义,但这些定义超出了本文的范围。

然而,我的想法促使我尝试以inversesplit的精神尝试另一个紧凑的split'定义:

inverse' :: (a -> b) -> (b -> a)
inverse' f (f x) = x
另一方面,这会导致以下错误:

Undefined data constructor `f'

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

换句话说ys中的split' (xs ++ ys) = (xs,ys)x似乎与inverse' f (f x) = x中的split'完全相似}。

或者如果与prefix (xs ++ _) = xs的类比不是很明显,请考虑orig (1 + x) = xload等,两者都编译并运行正常。

P.S。为了让这个问题更容易理解,我已经比原始帖子稍微调整了名称和类型签名。

2 个答案:

答案 0 :(得分:3)

简单地说,f x等函数模式的语法要求函数finverse'范围内可访问的已定义函数,这就是为什么xs ++ ys工作,f x没有。

这是由功能模式的实现所驱动的。它们被转换为对原始操作符=:<=的调用,执行一种&#34;懒惰&#34;统一(懒惰,因为它可以将自由变量绑定到表达式而不是值),其中模式中出现的变量作为新逻辑变量引入。因此,功能

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中都能正常工作。

请注意,一般不推荐显式使用原语操作符=:<=,因为它可能将逻辑变量绑定到表达式而不是值,因此违反了逻辑变量的语义(包含所有某个类型的值,但不是表达式)。功能模式的转换可确保无法观察到此违规,但可能是直接使用=:<=

最后,PAKCS和KiCS2也存在一个库FunctionInversion,它为invf1提供了invf5函数,用于反转具有不同arities的函数。

答案 1 :(得分:3)

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

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