这是我回答时的php:
function loop($A) {
$array1 = array();
$num = (int)$A;
if ($num == 0)
$array1 = "0";
for (int $i=0; $i<$num; $i++)
foreach (loop($i-$num) as &$value)
$array1[] = "+ ".$value." "; //concat
return $array1;
}
将上述代码直译为 Haskell 将是:
loop :: Int -> [String]
loop 0 = ["0"]
loop num = ["+ " ++ value ++ " " | i <- [0..num], value <- loop (i - num)]
它仍然没有实现任何目标,但它确实给了您在列表推导中 Haskell 的“循环”或迭代的味道。
首先要注意的是,类型签名loop :: Int -> [String]立即提醒我写loop 0 = ["0"],而不是loop 0 = "0"更确切地说是你所拥有的,但 Haskell 发现如果循环的输出有时是字符串列表,有时只是一个字符串,它的输出会不一致. 我认为这是一种值得学习的错误检查-也许您在修改时编写的所有代码都会在php中编译,但是由于设计不一致,Haskell不会-它迫使您在编写时思考清楚并修复错误在编译时间之前。
我将解释我的代码,而不是作为对 Haskell 的完整解释,而是作为品尝者并将其与您的代码相关联:
loop :: Int -> [String]
loop是一个接受Integer 并返回字符串列表的函数。Haskell 现在不允许您将其与任何其他数据类型一起使用,这意味着它是类型安全的,并且您可以直接从盒子中得到保护,避免各种讨厌的错误。类型系统实际上非常灵活、富有表现力和强大,这也是我们喜欢 Haskell 的原因之一,但在这里我使用它来锁定功能。
(列表在 Haskell 中被广泛使用,而不是数组。它们非常方便并且可以快速地进行顺序访问。有数组数据类型,但它们不那么可爱/Haskellish - 首先习惯于列表。)
loop 0 = ["0"]
这意味着如果您loop使用 Int调用0,它应该返回带有一个字符串“0”的列表。
loop num = [ something | stuff... ]
意味着您可以在其中获取变量的值stuff并将它们返回something,因此
loop num = [ "+ " ++ value ++ " " | stuff... ]
意味着我们将返回 (Haskell 的版本) "+ ".$value." "。这里我们使用++而不是 php 的..
i <- [0..num]
这意味着 let irange from0到num。它必须是Int因为num是因为loop :: Int -> ...。
value <- loop (i - num)
这意味着 let valuerange 跨越loop使用 number调用的结果i - num。
value必须是String因为loop :: Int -> [String]。
在 Haskell 中,就像递归调用被实现为表达式重写一样,因此它们在被调用时消失并且不会使堆栈混乱,除非您的计算本身会使堆栈变得混乱。
把它放在一起给出:
loop num = ["+ " ++ value ++ " " | i <- [0..num], value <- loop (i - num)]
如果这个符号感觉很奇怪,你可能会更喜欢命令式的语法:
loop :: Int -> [String]
loop 0 = ["0"]
loop num = do
i <- [0..num]
value <- loop (i - num)
return ("+ " ++ value ++ " ")
当然它仍然没有做任何有用的事情,但至少它很容易跟踪。
为什么不通过http: //learnyouahaskell.com/上的Learn You a Haskell for Great Good或http://book.realworldhaskell.org/上的Real World Haskell学习,这两个教程开始简单但深入。我认为您会发现 Haskell 是一种编写少量正确代码来替换大量 OK 代码的好方法。想得更清楚,写得更少!