我尝试编写自定义函数,它接受一个数组并迭代它,我需要打印每个数字并递归启动相同的函数但我得到错误
解析输入`main'
时的错误
代码:
firstitem n = if n /= [] n firstitem( tail n )
main = do
print(firstitem [1,2,3])
答案 0 :(得分:11)
您的第一个问题是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 block”。 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
最后,你的代码很漂亮。希望有所帮助。
答案 1 :(得分:1)
在Haskell中,if
总是需要一个else
分支。您还缺少then
,即您需要if CONDITION then TRUE_VAL else FALSE_VAL
形式的内容。
您可以通过使用模式匹配来完全避免if
。
要在执行期间打印进度,您可以使用Writer
monad。