4

我尝试编写带有数组并对其进行迭代的自定义函数,我需要打印每个数字并递归启动相同的函数,但出现错误

解析输入“主”错误

代码:

firstitem n = if n /= [] n firstitem( tail n )


main = do
    print(firstitem [1,2,3])
4

2 回答 2

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 块”。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

最后,你的代码很漂亮。希望有点帮助。

于 2012-10-16T07:37:25.560 回答
1

在 Haskell 中,if总是需要有一个else分支。您还缺少 a then,即您需要某种形式的东西if CONDITION then TRUE_VAL else FALSE_VAL

if您可以通过使用模式匹配来完全避免这种情况。

要在执行期间打印出进度,您可以使用Writermonad

于 2012-10-16T07:29:29.267 回答