通常,我头疼是因为我的推理有问题:
对于一组参数,引用透明函数将始终返回1组输出值。
这意味着这样的函数可以表示为真值表(一个表格,其中为一组参数指定了1组输出参数)。
这使得这些函数背后的逻辑是组合的(而不是时序的)。
这意味着使用纯函数式语言(只有rt函数的语言)只能描述组合逻辑。
最后一个陈述是从这个推理中推导出来的,但显然是错误的;这意味着推理有误。[问题:这个推理哪里错了?]
UPD2. 你们说了很多有趣的事情,但没有回答我的问题。我现在更明确地定义了它。抱歉搞乱了问题定义!
通常,我头疼是因为我的推理有问题:
对于一组参数,引用透明函数将始终返回1组输出值。
这意味着这样的函数可以表示为真值表(一个表格,其中为一组参数指定了1组输出参数)。
这使得这些函数背后的逻辑是组合的(而不是时序的)。
这意味着使用纯函数式语言(只有rt函数的语言)只能描述组合逻辑。
最后一个陈述是从这个推理中推导出来的,但显然是错误的;这意味着推理有误。[问题:这个推理哪里错了?]
UPD2. 你们说了很多有趣的事情,但没有回答我的问题。我现在更明确地定义了它。抱歉搞乱了问题定义!
编辑:虽然我显然错过了实际问题的核心,但我认为我的答案非常好,所以我会保留它 :-)(见下文)。
我想更简洁地表达这个问题:一个纯函数式语言能否计算出任何命令式语言可以计算出的东西?
首先,假设你拿一种命令式语言比如C语言,并使它不能在定义后更改变量。例如:
int i;
for (i = 0; // okay, that's one assignment
i < 10; // just looking, that's all
i++) // BUZZZ! Sorry, can't do that!
好的,你的for
循环就这样结束了。我们还能保留while
循环吗?
while (i < 10)
当然,但这并不是非常有用。因为i
无法更改,所以它要么会一直运行,要么根本不会运行。
那么递归呢?是的,你可以继续使用递归,而且它仍然非常有用:
int sum(int *items, unsigned int count)
{
if (count) {
// count the first item and sum the rest
return *items + sum(items + 1, count - 1);
} else {
// no items
return 0;
}
}
items
和count
实例,但sum((int[]){1,2,3}, 3)
总是评估为6
,所以如果你愿意,你可以将该表达式替换为6
。my_sum numbers = ??? where
i = 0
total = 0
在这里,你不能编写一个“for循环”来逐步增加i和total的值。但是并不是一无所有,只需使用递归来不断获取新的i和total
:
my_sum numbers = f 0 0 where
f i total =
if i < length numbers
then f i' total'
else total
where
i' = i+1
total' = total + (numbers !! i)
<注意,这是在Haskell中求数组和的愚蠢方法,但它展示了处理单一赋值的一种方法。>
<现在,考虑下面这段看起来高度命令式的代码:>
main = do
a <- readLn
b <- readLn
print (a + b)
实际上这只是语法糖,其实际含义为:
main =
readLn >>= (\a ->
readLn >>= (\b ->
print (a + b)))
a = readLn
readLn >>= (\x -> print (x + 1))
这个表达式的结果是一个操作值。如果Haskell起身执行这个操作,它会读取一个整数,将其加1并打印出来。通过将行动的结果绑定到执行某些操作的函数,我们可以在状态世界中玩耍,同时保持参照透明度。
>>=
和 return
函数。当你看到 IO Int
时,就想象一个动作,如果执行它,则会产生一个 Int。您可以使用 >>=
(绑定)运算符构建复合动作,而不是编写逐步执行的指令。>>=
运算符以奇妙有趣的方式用于其他类型。别害怕 "M" 字。 - Joey Adams以下是我对这个问题的看法:
任何系统都可以被描述为组合函数,无论大小。
纯函数只能处理组合逻辑并没有错,这种推理是正确的,只不过函数式语言在某种程度上隐藏了这一点。
你甚至可以将游戏引擎的工作描述为真值表或组合函数。
你可能有一个确定性函数,它以游戏引擎占用的 RAM 和键盘输入作为“整个游戏的当前状态”,并返回“游戏下一帧的状态”。返回值由输入中位的组合决定。
当然,在任何有意义和理智的函数中,输入都会被解析成整数、小数和布尔值的块,但这些值中位的组合仍然决定了函数的输出。
还要记住,基本的数字逻辑可以用真值表来描述。之所以不对超过4位整数的算术运算使用真值表,是因为真值表的大小呈指数级增长。