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 == 2
和inverse (*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)
以及其他一些颇具启发性的定义,但这些定义超出了本文的范围。
然而,我的想法促使我尝试以inverse
和split
的精神尝试另一个紧凑的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) = x
或load
等,两者都编译并运行正常。
P.S。为了让这个问题更容易理解,我已经比原始帖子稍微调整了名称和类型签名。
答案 0 :(得分:3)
简单地说,f x
等函数模式的语法要求函数f
是inverse'
范围内可访问的已定义函数,这就是为什么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中有详细描述(但未由当前编译器检查)。因此,不允许使用功能模式中的函数变量。
有人可能会考虑扩展这一点,但这超出了当前功能模式的基础。