我尝试编写带有数组并对其进行迭代的自定义函数,我需要打印每个数字并递归启动相同的函数,但出现错误
解析输入“主”错误
代码:
firstitem n = if n /= [] n firstitem( tail n )
main = do
print(firstitem [1,2,3])
您的第一个问题是您的if
语句语法错误。你应该写
firstItem n = if {- condition-}
then {- do this -}
else {- do that -}
其次,不清楚该功能firstItem
应该做什么。听起来它应该返回列表的第一项,但是您的描述看起来好像您想要遍历列表的所有元素。
您可以将迭代和打印组合成一个函数,如下所示:
printAll xs = if null xs -- If the list is empty
then return () -- then we're done, so we quit.
else do print (head xs) -- Otherwise, print the first element
printAll (tail xs) -- then print all the other elements.
main = printAll [1,2,3]
如果列表为空,该函数null
返回True
,否则返回False
。您可以将语句return ()
想象为“没有什么要处理的,所以现在停止函数并且不返回任何结果”。第三行和第四行包含一个“do 块”。do 块基本上是一种胶水,将两个动作绑定在一起print (head xs)
,printAll (tail xs)
形成一个动作。您可以用花括号编写它以使其更清晰:
do {
print (head xs);
printAll (tail xs)
}
尽管您实际上并不需要它们-缩进指定了您的意思。
这解决了你的问题,但它有点笨拙。毕竟,Haskell 应该是一门漂亮的语言——所以让我们让你的代码更漂亮吧!最好使用模式匹配将列表分成头部和尾部:
printAll [] = return ()
printAll (x:xs) = do print x
printAll xs
那好多了。但它可以更加模块化。嘿,也许我们可以创建一个通用函数,将动作作为输入,并对列表的每个元素执行该动作:
repeatedly f [] = return ()
repeatedly f (x:xs) = do f x
repeatedly f xs
printAll xs = repeatedly print xs
那很整齐。但实际上,已经有一个函数可以做到这一点。它被称为mapM_
(它被称为这个是有充分理由的,但我现在不会进入它)并且它在Control.Monad
模块中:
import Control.Monad
printAll xs = mapM_ print xs
实际上,您可以省略xs
参数,编译器可以推断它应该存在:
printAll = mapM_ print
最后,你的代码很漂亮。希望有点帮助。
在 Haskell 中,if
总是需要有一个else
分支。您还缺少 a then
,即您需要某种形式的东西if CONDITION then TRUE_VAL else FALSE_VAL
。
if
您可以通过使用模式匹配来完全避免这种情况。
要在执行期间打印出进度,您可以使用Writer
monad。