在haskell中输入后调用函数

时间:2012-06-10 13:32:19

标签: list function haskell input

这是家庭作业的一部分。 我需要编写一个函数,从输入读取信息直到空行。之后,该函数将第一个,第三个,第五个...行符号作为一个字符串,第二个,第四个...作为另一个字符串。 签名为combine :: IO (String , String)

我编写了一个以列表作为参数的函数,并将1,3,5 ..添加到String个2,4,6个符号到另一个String。功能在这里:

intotwo (x : xs)
   = let
      (us , vs)
         = intotwo xs
   in
   (x : vs , us)
intotwo _
   = ([] , []) 

此外,我编写了一个读取输入的代码:它在这里:

combine
   = do
      lines <- getLine
      if null lines
         then return ([], [])
         else do
            linesagain <- combine
            return --what should I return?

有人可以帮我完成作业(可选:提供一些提示)?

2 个答案:

答案 0 :(得分:5)

我会提供一些提示来帮助您解决问题。

首先,为您定义的所有功能提供类型是一个巨大的帮助。这样,编译器可以立即告诉您函数是否正在执行您认为正在执行的操作。当您需要将程序的不同部分连接在一起时,它还可以帮助您。

其次,每个功能只解决一个问题是一个非常好的主意。你的intotwo函数很好地遵循这个功能,它可以很好地分割列表。然而,你的组合功能似乎试图做太多,这将使它更难写。我会将该函数分成两个较小的函数。

最后,有一个非常有用的特殊功能叫undefined。这匹配任何类型,并帮助您编写函数。诀窍是从整个函数开始等于未定义(并且编译但在运行时崩溃),并逐步改进函数,直到它完成你想要的并且没有更多的未定义。

首先,我要为intotwo函数添加一个类型签名。类型为[a] -> ([a], [a])

接下来,我将编写一个函数,从输入读取行直到它到达空行,然后返回读取的行列表。此函数的类型为:

readLinesUntilEmpty :: IO [String]
readLinesUntilEmpty = undefined

几乎这样做的实现是这样的:

readLinesUntilEmpty = do
  nextLine <- getLine
  rest <- readLinesUntilEmpty
  return (nextLine : rest)

然而,这永远不会停止阅读(注意未检查nextLine是否为空)。

以下函数显示了如何执行此操作(但我将部分实现退出):

readLinesUntilEmpty = do
  nextLine <- getLine
  case nextLine of
    "" -> do
      undefined -- TODO fix me
    _ -> do
      undefined -- TODO fix me

你应该能够从中找出其余部分。

接下来,您的intotwo函数返回两个字符串列表,但您需要再次将它们连接在一起。例如,["this", "that"]应变为"this\nthat"。这种函数的类型是[String] -> String

joinLines :: [String] -> String
joinLines = undefined -- TODO

这是一个比inttotwo func更容易编写的函数,所以你应该没问题。

最后,您可以将这三个功能链接在一起以获得结果:

combine :: IO (String, String)
combine = do
  lines <- readLinesUntilEmpty
  let (oddLines, evenLines) = intotwo lines
  return $ (joinLines oddLines, joinLines evenLines)

答案 1 :(得分:0)

由于您需要多个字符串读取,因此需要递归输入。或者你可以使用getContents,但我不确定它是否适合交互式I / O. 像这样:

combine = getContents
          >>= return . intotwo