这是我回答时的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
是一个接受Int
eger 并返回字符串列表的函数。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 i
range from0
到num
。它必须是Int
因为num
是因为loop :: Int -> ...
。
value <- loop (i - num)
这意味着 let value
range 跨越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 代码的好方法。想得更清楚,写得更少!