8

我刚刚开始学习haskell,它的思维方式与我习惯的方式(C 风格的语言)大不相同。

无论如何,对于我正在处理的一个问题,我需要接收用户输入。它将以形式出现

2
10
20

例如。格式是第一行表示后面的行数。我的第一个想法是我会阅读第一行,然后循环运行该次数。虽然这是 Haskell!据我所知,循环是不可能的。

我的下一个想法是,我将使用第一行输入来填充一个列表,其中包含后面的其他 n 个数字。我不知道我会怎么做。我在这里是因为我什至不确定我会寻找什么来解决这个问题。

提前感谢您向我展示了执行此操作的 Haskell 方法。到目前为止很难,但我听到“开明”的人的好评如潮,所以我认为自己学习语言不会有什么坏处。

这是可以运行一次的代码,但需要为第一行之后的第二行到 n 行中的每一行运行一次。

l n = (-1)^n/(2*(fromIntegral n)+1)
a m = sum [l n | n <- [0..(m-1)]]
main =
    do  b <- readLn
        print (a b)

(另外,我很想听听我是否可以对我的代码进行其他改进,但在这种特定情况下,它是为了让比赛以尽可能少的字符数解决问题。我不想得到更多特别是在其他人试图寻找相同问题的答案的情况下。)

编辑:感谢大家的回答。我最终得到了一些我想要的东西。我将代码放在下面以供后代使用。可悲的是,即使它以出色的成绩通过了测试用例,但他们测试它的实际数据却不同,他们告诉我的只是我得到了“错误的答案”。此代码“有效”,但无法为您提供正确答案。

import Control.Monad
l n = (-1)^n/(2*(fromIntegral n)+1)
a m = sum [l n | n <- [0..(m-1)]]
main =
    do  b <- readLn
        s <- replicateM b readLn
        mapM_ print [a c | c <- s]
4

4 回答 4

10

首先,您可以在 haskell 中很好地循环。它一直在发生。您只是没有语法结构,因为不需要它们。

大多数时候,常见的通用循环被放入库中。在这种情况下,您需要的循环位于标准库的模块中Control.Monad。它被称为replicateM。它具有类型签名Monad m => Int -> m a -> m [a]。要针对您的案例专门使用此签名,它的类型应为Int -> IO Int -> IO [Int]. 第一个参数是循环的次数。第二个是在每个循环上运行的 IO 操作。该函数的结果是一个生成输入列表的 IO 操作。

因此,如果您添加inputs <- replicateM b readLn到 do 块,它会将一个名为的列表inputs放入范围,其中包含来自b第一个输入行之后的值。然后,您可以将您的解决方案功能映射到这些线上。

于 2013-02-03T00:41:27.563 回答
7

卡尔的解决方案会奏效,但它有点不透明。如果你想把它写出来,你可以这样做:

readLines :: Int -> IO [Int]
readLines 0 = return []
readLines n = do
   x <- fmap read getLine
   rest <- readLines (n-1)
   return $ x : rest

readSomeNumberOfLines :: IO [Int]
readSomeNumberOfLines = do
   n <- fmap read getLine
   readLines n

你在这里所做的readLines是你基本上定义了明显的基本情况(读取 0 个东西,只需给出一个空列表)和递归情况(读取 n 个东西,读取一个东西,然后读取另一个 n-1东西,然后将它们组合在一起)。

于 2013-02-03T00:52:58.683 回答
2

我不确定您到底想做什么,但是要读取一个整数 n 然后接下来的 n 行作为整数,您可以执行以下操作:

import Control.Monad

-- read n, then sum integers read from the next n lines
test = do n <- readLn
          xs <- replicateM n readLn
          return $ sum xs

当然最后的return $ sum xs不是实质性的 - 如果它不在那里,你需要一个明确的类型签名test

如果您不了解这些功能中的任何一个,那就胡说八道

于 2013-02-03T01:00:57.773 回答
1

您可以创建一个readInput nwheren是要读取的行数。n调用 this 递归地从每次减去 1 。我也是 Haskell 菜鸟,所以这可能不是最好的方法。不过,它应该仍然有效。

于 2013-02-03T00:46:09.593 回答