简体   繁体   English

在haskell中输入后调用函数

[英]calling function after input in haskell

It is a part of a homework. 这是家庭作业的一部分。 I need to write a function that reads info from the input until empty line. 我需要编写一个从输入读取信息直到空行的函数。 After that function puts first, third, fifth ... line symbols as one String and second, fourth ... as another String. 在该函数之后,将第一,第三,第五...行符号作为一个字符串,将第二,第四...作为另一字符串。 Signature is combine :: IO (String , String) 签名combine :: IO (String , String)

I have written a function that takes a list as argument and puts 1,3,5.. to one String a 2,4,6 symbols to another String . 我编写了一个函数,该函数将列表作为参数,并将1,3,5 ..放在一个String将2,4,6个符号放在另一个String Function is here: 功能在这里:

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

Also I have written a code that reads an input: It is here: 我还编写了一个读取输入的代码:在这里:

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

Can anybody help me to finish my homework (optional: give some tips)? 有人可以帮我完成作业吗(可选:提供一些技巧)?

I'll give a few hints to help you solve your problem. 我会给您一些提示,以帮助您解决问题。

Firstly, it is a HUGE help to give types to all the functions you define. 首先,为您定义的所有函数提供类型是一个巨大的帮助。 This lets the compiler tell you immediately if a function isn't doing what you think it is doing. 这使编译器可以立即告诉您函数是否没有按照您认为的那样做。 It also helps you when you need to join different parts of your program together. 当您需要将程序的不同部分连接在一起时,它也可以为您提供帮助。

Secondly, it is a very good idea to only solve one problem per function. 其次,每个功能仅解决一个问题是一个很好的主意。 Your intotwo function follows this well, it does its job of splitting a list very well. 您的intotwo函数很好地遵循了这一点,它很好地完成了拆分列表的工作。 Your combine function however looks like it is trying to do too much, which will make it harder to write. 但是,您的Combine函数似乎正在尝试做太多事情,这将使编写变得更加困难。 I would split that function into two smaller functions. 我会将那个功能分成两个较小的功能。

Finally, there is a very useful special function called undefined . 最后,有一个非常有用的特殊函数,称为undefined This matches any type, and helps you write a function. 这可以匹配任何类型,并有助于您编写函数。 The trick is to start with the whole function equalling undefined (and compiling but crashing when run), and progressively improve the function until it does what you want and has no more undefines in it. 诀窍是从整个函数等于未定义开始(并且编译但在运行时崩溃),并逐步改进该函数,直到它完成您想要的操作并且其中没有更多未定义为止。

So firstly, I would add a type signature to the intotwo function. 因此,首先,我将一个类型签名添加到intwo函数中。 THe type is [a] -> ([a], [a]) . 类型是[a] -> ([a], [a])

Next, I would write a function that reads lines from input until it hits an empty line, then returns the list of lines read. 接下来,我将编写一个函数,该函数从输入中读取行,直到遇到空行,然后返回读取的行的列表。 This function would have the type: 该函数的类型为:

readLinesUntilEmpty :: IO [String]
readLinesUntilEmpty = undefined

An implementation that nearly does this is this: 一个几乎可以做到这一点的实现是这样的:

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

However this never stops reading (note how nextLine isn't checked for being empty). 但是,这永远不会停止读取(请注意如何不检查nextLine是否为空)。

the following function shows how you can do this (but I'm leaving some of the implementation out): 以下函数显示了如何执行此操作(但我省略了一些实现):

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

You should be able to figure out the rest from there. 您应该能够从那里找出其余的内容。

Next, your intotwo function returns two lists of strings, but you are expected to join them together again. 接下来,您的intotwo函数将返回两个字符串列表,但是希望您将它们再次结合在一起。 Eg ["this", "that"] should turn into "this\\nthat" . 例如["this", "that"]应该变成"this\\nthat" The type of such a function is [String] -> String : 此类函数的类型为[String] -> String

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

This is an easier function to write than the inttotwo func, so you should be fine. 这个函数比inttotwo函数更容易编写,因此应该没问题。

Finally, you can link those three functions together to get your result: 最后,您可以将这三个功能链接在一起以获得结果:

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

Since you need multiple strings reading, you need a recursive input. 由于需要读取多个字符串,因此需要递归输入。 Or you can just use getContents, but i'm not sure whether it's good for interactive I/O. 或者,您可以只使用getContents,但是我不确定它是否适合交互式I / O。 Something like this: 像这样:

combine = getContents
          >>= return . intotwo

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM