我有一个有趣的问题,但我不确定如何用它来表达...
考虑lambda演算.对于给定的lambda表达式,有几种可能的缩减顺序.但其中一些不会终止,而另一些则会终止.
在lambda演算中,事实证明存在一个特定的减少顺序,如果实际存在,则保证总是以不可简化的解决方案终止.它被称为正常秩序.
我写了一个简单的逻辑解算器.但麻烦的是,它处理约束的顺序似乎对它是否找到任何解决方案产生了巨大影响.基本上,我想知道我的逻辑编程语言是否存在类似正常顺序的东西.(或者说,单纯的机器无法确定地解决这个问题.)
这就是我所追求的.据推测,答案关键取决于"简单逻辑解算器"到底是什么.所以我将尝试简要描述一下.
我的节目紧密地基于编程乐趣(Jeremy Gibbons&Oege de Moor)第9章中的组合系统.该语言具有以下结构:
求解器的输入是单个谓词.谓词可能涉及变量.求解器的输出为零或更多解.解决方案是一组变量赋值,它使谓词成为正确.
变量持有表达式.表达式是整数,变量名或子表达式的元组.
有一个等式谓词,用于比较表达式(不是谓词)的相等性.如果用其值替换每个(绑定)变量使两个表达式相同,则会感到满意.(特别是,每个变量都等于它自己,绑定与否.)这个谓词是使用统一来解决的.
还有AND和OR的运算符,它们以明显的方式工作.没有NOT运算符.
有一个"存在"运算符,它基本上创建局部变量.
定义命名谓词的工具支持递归循环.
关于逻辑编程的一个"有趣的事情"是,一旦你编写了一个命名谓词,它通常会向前和向后(有时甚至是横向).典型示例:用于连接两个列表的谓词也可用于将列表拆分为所有可能的对.
但有时向后运行谓词会导致无限搜索,除非您重新排列术语的顺序.(例如,交换一个AND的LHS和RHS或者一些OR.)我想知道是否有一些自动方法来检测运行谓词的最佳顺序,以确保在解决方案集完全正确的所有情况下立即终止有限.
有什么建议?
我目前正试图在我的一个C程序中理解一些非常奇怪的行为.显然,在它结尾处添加或删除看似无关紧要的行会大大影响程序其余部分的性能.
我的程序看起来有点像这样:
int large_buffer[10000];
void compute(FILE * input) {
for(int i=0; i<100; i++) {
do_lots_of_stuff();
printf(".");
fflush(stdout);
}
}
int main() {
FILE *input = fopen("input.txt", "r");
compute(input);
fclose(input); // <--- everything gets 2x slower if I comment this out (!)
return 0;
}
Run Code Online (Sandbox Code Playgroud)
理论上,fclose(input)主函数末尾的那一行应该无关紧要,因为OS无论如何都应该在程序结束时自动关闭文件.但是我观察到当我将fclose语句包含在内时,我的程序需要2.5秒才能运行.差异2倍!这不是由于程序开始或结束时的延迟:在.使用fclose语句的版本中打印输出的速度明显更快.
我怀疑这可能与某些内存对齐或缓存未命中问题有关.如果我用另一个函数(如ftell)替换fclose,它也需要5s来运行,如果我减小large_bufferto <= 8000元素的大小,那么它总是在2.5秒内运行,无论fclose语句是否存在.
但我真的希望能够100%确定这种奇怪行为背后的罪魁祸首.是否有可能在某种分析器或其他工具下运行我的程序,这些工具会给我这些信息?到目前为止,我尝试运行两个版本,valgrind --tool=cachegrind但它报告了我的程序的两个版本的相同数量的缓存未命中(0%).
编辑1:运行我的程序的两个版本后,我perf stat -d -d -d得到以下结果:
Performance counter stats for './no-fclose examples/bench.o':
5625.535086 task-clock (msec) # 1.000 CPUs utilized
38 context-switches …Run Code Online (Sandbox Code Playgroud) 我希望将一个普通的旧函数作为类常量.但是,Python"有帮助"将它变成了一种方法:
class C(object):
a = 17
b = (lambda x : x+1)
print C.a # Works fine for int attributes
print C.b # Uh-oh... is a <unbound method C.<lambda>> now
print C.b(1) # TypeError: unbound method <lambda>() must be called
# with C instance as first argument (got int instance instead)
Run Code Online (Sandbox Code Playgroud)
我正在为Chomp游戏编写一个程序.你可以在维基百科上阅读游戏的描述,但无论如何我都会简要描述一下.
我们在尺寸为nxm的巧克力棒上玩,即酒吧分为nxm正方形.在每个回合中,当前玩家选择一个正方形并吃掉所选正方形下方和右侧的所有内容.因此,例如,以下是有效的第一步:

目的是迫使你的对手吃掉最后一块巧克力(它被中毒).
关于AI部分,我使用了具有深度截断的minimax算法.但是我无法想出合适的位置评估功能.结果是,通过我的评估功能,人类玩家很容易赢得我的计划.
谁能:
我通常坚信在我编程的大多数语言中都使用命名空间(合格的模块名称),因为一目了然地知道某个标识符的来源是非常好的.在Haskell中,还有一个额外的优点,即避免使用Prelude函数进行常见的名称冲突.
但是,我觉得必须在中缀符号(或其他简短的DSL-y标识符)上放置名称空间看起来很奇怪,所以我很想重新出口值,如下所示:
import qualified Data.Sequence as Seq
(|>) = (Seq.|>)
(<|) = (Seq.<|)
Run Code Online (Sandbox Code Playgroud)
现在困扰我的是那个
手动重新出口的价值感觉就像无聊的样板.
手动重新导出的值绕过现有的模块系统,似乎不适用于数据构造函数(可能还有其他我未遇到过的东西)
import qualified Data.Sequence as Seq
(:>) = (Seq.:>) --gives me a parse error:
--"Not in scope: data constructor `:>'"
Run Code Online (Sandbox Code Playgroud)如何协调中缀符号和命名空间?我应该放弃并学会命名一切吗?是否有关于命名空间和符号的Haskell最佳实践?
我想写一个函数,通过一个列表更新累加器,直到累加器达到某个条件或我到达列表的末尾.例如,产品功能在其累加器达到零时立即停止.
我知道如何通过手工编写递归来编写代码:
{-# LANGUAGE BangPatterns #-}
prod :: [Integer] -> Integer
prod xs =
go 1 xs
where
go 0 _ = 0
go !acc [] = acc
go !acc (x:xs) = go (acc * x) xs
Run Code Online (Sandbox Code Playgroud)
但有没有办法使用折叠和其他更高阶函数来编码?
想到的一件事是定义
mult 0 _ = 0
mult x y = x * y
Run Code Online (Sandbox Code Playgroud)
然后使用foldl'.然而,这并没有提前爆发,因此它有点浪费性能.
我们不能使用foldr,因为它以错误的顺序通过列表,它的"早期爆发"的方式是通过查看列表的元素而不是查看累加器(如果累加器有一个,这将是重要的不同于列表元素的类型).
我有一个递归数据类型,它有一个Functor实例:
data Expr1 a
= Val1 a
| Add1 (Expr1 a) (Expr1 a)
deriving (Eq, Show, Functor)
Run Code Online (Sandbox Code Playgroud)
现在,我有兴趣修改此数据类型以支持一般递归方案,因为本教程和此Hackage包中对它们进行了描述.我设法让catamorphism工作:
newtype Fix f = Fix {unFix :: f (Fix f)}
data ExprF a r
= Val a
| Add r r
deriving (Eq, Show, Functor)
type Expr2 a = Fix (ExprF a)
cata :: Functor f => (f a -> a) -> Fix f -> a
cata f = f . fmap (cata f) . unFix
eval :: …Run Code Online (Sandbox Code Playgroud) 我试图推断以下表达式的类型:
let rec fix f = f (fix f)
Run Code Online (Sandbox Code Playgroud)
应该给出类型 (a -> a) -> a
使用自下而上的算法(在概括hindley-milner类型推理算法中描述)后面添加了以下规则:
a1, c1 |-BU e1 : t1 B = fresh var
---------------------------------------------------------
a1\x, c1 U {t' == B | x : t' in A} |-BU let rec x = e1 : t
Run Code Online (Sandbox Code Playgroud)
我留下以下类型: t1 -> t2
以及以下限制:
t0 = fix
t1 = f
t2 = f (fix f)
t3 = f
t4 = fix f
t5 = fix
t6 = f
t3 = …Run Code Online (Sandbox Code Playgroud) haskell functional-programming type-inference ml hindley-milner
一些Lua函数返回nil以通知用户该函数不能执行某些任务(例如tonumber(),string.find()).
在C中,returnig nil就是这样完成的:
int some_function(lua_State* L) {
...
if (some condition) {
lua_pushnil(L);
return 1;
}
...
}
Run Code Online (Sandbox Code Playgroud)
但是,我想知道是否可以做以下事情:
int some_function(lua_State* L) {
...
if (some condition) {
return 0;
}
...
}
Run Code Online (Sandbox Code Playgroud)
它更短.我尝试了它似乎有效,但我不知道这是否是按设计的.我检查了Lua的源代码,我没有看到这种return 0模式,所以我想知道这样做是否合法.
两种不同的返回方式是否nil相同?
(顺便说一句,我知道所有关于通过异常发出的信号错误(也就是说),lua_error()所以请不要提及它.)
更新:
我现在看到两种方法之间存在细微的差别:print((function() end)())没有打印,而是print((function() return nil end)())打印"nil".我不知道这有多重要.
haskell ×6
c ×2
recursion ×2
algorithm ×1
cachegrind ×1
catamorphism ×1
class ×1
cpu-cache ×1
fold ×1
heuristics ×1
logic ×1
lua ×1
minimax ×1
ml ×1
module ×1
namespaces ×1
operators ×1
performance ×1
profiling ×1
python ×1
typeclass ×1