从咖喱教程的 3.13.3节:
剩余的操作称为刚性操作,而缩小的操作称为灵活操作.所有已定义的操作都是灵活的,而大多数基本操作(如算术运算)都是严格的,因为猜测对它们来说不是一个合理的选择.例如,prelude定义了一个列表连接操作,如下所示:
infixr 5 ++
...
(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
(x:xs) ++ ys = x : xs ++ ys
Run Code Online (Sandbox Code Playgroud)
由于操作"++"是灵活的,我们可以使用它来搜索满足特定属性的列表:
Prelude> x ++ [3,4] =:= [1,2,3,4] where x free
Free variables in goal: x
Result: success
Bindings:
x=[1,2] ?
Run Code Online (Sandbox Code Playgroud)
另一方面,诸如加"+"之类的预定义算术运算是刚性的.因此,使用逻辑变量作为参数的"+"调用flounders:
Prelude> x + 2 =:= 4 where x free
Free variables in goal: x
*** Goal suspended!
Run Code Online (Sandbox Code Playgroud)
库里似乎没有防止写入将被暂停的目标.什么类型的系统可以提前检测到目标是否会被暂停?
我想问一下从头开始/逆向工程师实施什么样的正式系统会更有趣.
我查看了一些逻辑/声明性编程系统的现有和开源项目.我决定在空闲时间编写类似的内容,或者至少要了解实现的一般概念.
如果这些系统中的一些能够提供逻辑中现代学术研究的大部分表达能力和简洁性以及它与计算模型的关系,那将是很好的.
你建议至少在概念层面学习什么?例如,Lambda-Prolog很有意思,因为它允许更高阶的关系,但AFAIK基于直觉主义逻辑,因此缺乏排除中间原则; 这通常对我不利.
我也欢迎任何有关现代逻辑编程系统的建议,这些系统不太受欢迎,但更具表现力/强大功能.
考虑一个函数choose在库里的编程语言与"规范(choose xs)的非确定性选择一个元素从列表中xs".
我将通过两个替代的非确定性规则直接实现它:
choose :: [a] -> a
choose x:_ = x
choose _:xs = choose xs
Run Code Online (Sandbox Code Playgroud)
但是在Muenster Curry Compiler的 /usr/lib/curry-0.9.11/Success.curry中,它使用辅助函数定义:
choose (x:xs) = choosep x xs
where choosep x [] = x
choosep x (_:_) = x
choosep _ (x:xs) = choosep x xs
Run Code Online (Sandbox Code Playgroud)
编译器提供的模块定义的优点(如果有的话)是什么?2个定义是否完全等价(即使在一些非确定性和未定义值的棘手情况下)?在某些情况下,其中一个更有效吗?
cthom06(谢谢!)已经正确地指出我的定义会导致在更多情况下达到未定义的值(因为我们会尝试使用一个空列表参数调用此函数,每次我们的"顶级"调用一次非空列表参数).(嗯,为什么我没有立刻注意到这个考虑因素?..)效率较低.
但我想知道:有任何语义差异吗?可能在一些棘手的情况下,差异是否重要?
我们看到两个定义之间的差异 - 在非空列表的情况下 - 基本上归结为两个潜在定义之间的差异id:
我的定义就像定义id为:
id x = x
id _ = undefined
Run Code Online (Sandbox Code Playgroud)
他们的定义就像定义id正常的方式:
id …Run Code Online (Sandbox Code Playgroud) recursion functional-programming list non-deterministic curry
我对Prolog的力量感到非常惊讶.花了一些时间来解决问题,但对我来说,它似乎是那里最酷的声明性语言.这就是为什么最近,在使用Scala进行了两年的函数式编程之后,我决定再次看一下逻辑编程,以"训练我的大脑"或更好地实际使用.
结合功能和逻辑编程似乎对我学习/巩固两种声明范式的概念很有吸引力.我发现强力型系统非常有用且引人入胜.
Scala真的与interop一起闪耀.我们不要重新发明轮子.它应该能够用另一种主要语言调用代码,并且最好也可以调用.但它不一定是Java.C或Haskell也可以.
那么,今天最有用和最具启发性的FLP语言,您对它们的看法和建议是什么?
这是我到目前为止发现的:
水星:声称是快速,强类型的Prolog.纯粹的声明,但没有逻辑变量!没有约束编程?似乎是使用最广泛的FLP.互操作?
库里:看起来很有前途,也是最先进的,但现在文档上有点低."实验"是否意味着不成熟/不准备潜入?只是基于Haskell或实际上与Haskell的良好互操作?
Ciao:似乎提供了我想要的许多功能,但Stack Overflow似乎根本不知道它,虽然它自1984年以来就存在了?它出什么问题了?互操作?
drools(java library/DSL):声称它允许混合前向和后向链接.成熟.直接与Java/Scala互操作,但依赖于可变数据/命令式构造?它与功能JVM语言的集成程度如何?
miniKanren:实现存在于多个平台上.如何互操作?高效?
Lambda Prolog实现,例如:
良好但理论上的阅读并偏向于咖喱,而不是解决实际问题:
我有一个表示谓词逻辑公式的标准数据类型.表示析出的自然演绎消除规则的函数可能如下所示:
d_el p q =
if p =: (Dis r s) && q =: (Neg r) then Just s else
if q =: (Dis r s) && p =: (Neg r) then Just s else
Nothing where r,s free
x =: y = (x =:= y) == success
Run Code Online (Sandbox Code Playgroud)
在统一失败时,该函数不返回Nothing,而是返回以下解决方案PACKS:
logic> d_el (Dis Bot Top) (Not Bot)
Result: Just Top
More Solutions? [Y(es)/n(o)/a(ll)] n
logic> d_el (Dis Bot Top) (Not Top)
No more solutions.
Run Code Online (Sandbox Code Playgroud)
我错过了什么,为什么在统一失败时不el评价Nothing?
我在维基百科上找到了Curry.它说库里几乎是一个超集,但不是因为缺乏某些东西.
我希望看到它支持整个Haskell.他们是否计划将Haskell作为Curry的一部分实施?
lodash的新手,并尝试使用它来获得更多的了解。我不了解以下代码的行为。
在了解到的arity参数之后_.curry,我得到了一个代码片段,该片段产生的结果对我来说似乎很奇怪。
const words = ['jim', 'john'];
const pad10 = words =>
_.map(words, word => _.pad(word, 10));
console.log(pad10(words)); // [ ' jim ', ' john ' ]
const flipMap = _.flip(_.map);
const flipPad = _.flip(_.pad);
const curriedFlipMap = _.curry(flipMap, 2);
const pad10v2 = curriedFlipMap(word => flipPad(' ', 10, word));
console.log(pad10v2(words)); // [ ' jim ', ' john ' ]
const curriedFlipPad = _.curry(flipPad, 3);
const padWord10 = curriedFlipPad(' ', 10);
const pad10v3 = curriedFlipMap(word => padWord10(word));
console.log(pad10v3(words)); // …Run Code Online (Sandbox Code Playgroud)当我配置 curry 的编译器锌时,我得到了这个:
checking for Haskell 98 compiler...
checking for ghc... ghc
checking ghc version... 7.0
checking whether ghc supports Haskell 98... [1 of 1] Compiling Main ( conftest.hs, conftest.o )
yes
using ghc for compilation
checking how to import IOExts... configure: error: import of IOExts does not work
Run Code Online (Sandbox Code Playgroud)
那么什么是 IOExts?我在哪里可以找到它?
Curry与它的堂兄 Haskell 不同,它允许您为一个函数赋予多个值:
foo 1 2 = 3
foo 1 2 = 4
Run Code Online (Sandbox Code Playgroud)
它确实回溯(或其他一些搜索)来探索这种非确定性的影响。
这使它类似于 Prolog(特别是?Prolog由于类型系统和语法),您可以在其中声明
foo 1 2 3.
foo 1 2 4.
Run Code Online (Sandbox Code Playgroud)
在语义上,N 元Curry 函数和N+1 元Prolog 关系之间有什么区别吗?
functional-programming prolog logic-programming curry lambda-prolog
如果f ::(a,b) - > c,我们可以定义curry(f)如下:
咖喱(f)::((a,b) - > c) - > a - > b - > c
const curry = f => a => b => f(a, b);
const sum = curry((num1, num2) => num1 + num2);
console.log(sum(2)(3)); //5
Run Code Online (Sandbox Code Playgroud)
我们如何实现带有n个参数的函数的通用咖喱函数?
t2 = (\x y z-> x.y.x)
GHCI告诉我这个:
t2 :: (b1 -> b2) -> (b2 -> b1) -> p -> b1 -> b2
我无法理解这种类型的签名是如何形成的.到目前为止,我已经认为r-most-x基本上是一个函数,它接受a b2并返回a b1,那么这b1是中间函数的输入y,并b2再次输出?它不应该返回新类型的值b3或什么?