Haskell输入返回元组

nic*_*las 4 io haskell interactive

我想知道IO()函数可以返回元组,因为我想将这些函数作为另一个函数的输入.

investinput :: IO()->([Char], Int)
investinput = do
 putStrLn "Enter Username : "
 username <- getLine

 putStrLn "Enter Invest Amount : "
 tempamount <- getLine
 let amount = show  tempamount
 return (username, amount)
Run Code Online (Sandbox Code Playgroud)

请帮忙.

谢谢.

Ant*_*sky 8

Haskell中的IO在您习惯使用的语言中不像IO那样工作.Haskell中的所有函数都必须是纯粹的:也就是说,如果f使用参数调用函数x,则调用它一次,两次或一百次之间必须没有区别.考虑一下这对IO意味着什么.天真地,getLine应该有类型getLine :: String,或者也许getLine :: () -> String.(()是单位类型,它的唯一值是();它有点像C语言中的void类型,但它有一个值.)但这意味着每次你写getLine,它都必须返回在相同的字符串,这是不是你想要的.这是IO类型的目的:封装动作.这些行动与功能不同; 它们代表不纯的计算(虽然它们本身就是纯粹的).type的值IO a表示一个操作,该操作在执行时返回type的值a.因此,getLine具有类型getLine :: IO String:每次评估动作时,String产生a(通过从用户读取).同样,putStr有类型putStr :: String -> IO (); 它是一个函数,它接受一个字符串并返回一个动作,当它运行时,它不会返回任何有用的信息......但是,作为副作用,它会向屏幕输出一些内容.

您正在尝试编写类型的函数IO () -> ([Char], Int).这将是一个函数,它将一个动作作为输入并返回一个元组,这不是你想要的.你想要一个IO (String, Int)-an动作,它在运行时会产生一个由字符串(它是一个同义词[Char])和一个整数组成的元组.你的当前代码也差不多了!这就是你需要的:

investinput :: IO (String, Int)
investinput = do
  putStrLn "Enter Username : "
  username <- getLine
  putStrLn "Enter Invest Amount : "
  tempamount <- getLine
  let amount = read tempamount
  return (username, amount)
Run Code Online (Sandbox Code Playgroud)

请注意,我只进行了两次更改(并删除了一个空行).首先,我已经改变了函数的类型,就像我上面说的那样.其次,我改变showread.该show函数具有以下类型Show a => a -> String:它是一个函数,它接收可以显示的任何内容并生成表示它的字符串. 想要的read,它有类型Read a => String -> a:给定一个字符串,它解析它并返回一些可读的值.

你问的另一件事是返回一个元组(String, Int)而不是一个动作IO (String, Int).没有纯粹的方法可以做到这一点; 换句话说,没有纯粹的功能IO a -> a.为什么是这样?因为IO a代表了一种取决于现实世界的不纯净的行为.如果我们有这样的函数impossibleRunIO :: IO a -> a,那么我们希望它是这样的impossibleRunIO getLine == impossibleRunIO getLine,因为函数必须是纯的.但这没用,因为我们希望impossibleRunIO能够真实地与现实世界互动!因此,这种纯粹的功能是不可能的.进入的一切IO都永远不会离开.这就是return:它是一个函数,在这种情况下为1,类型return :: a -> IO a,使您可以将纯值放入IO.对于任何x,return x是一种在运行时始终产生的动作x.这就是为什么你必须结束你的doreturn:username是一个从一个动作中提取的纯值,因此只在do块中可见.IO在外界看到它之前,你需要把它抬起来.amount/ 也是如此tempamount.

而且为了完整起见:这背后有一些总体理论将它联系在一起.但是开始Haskell编程根本没有必要.我建议你做的是将大部分代码构造成纯粹的函数,这些函数可以折叠,控制和毁坏你的数据.然后构造一个薄的(尽可能薄的)IO前层,它与所述功能相互作用.你会惊讶于你需要多少IO!

1:它实际上有一个更通用的类型,但这与当下无关.

  • 你的观点当然是正确的,但根据报道,"main"只需要为某种类型的"t`"输入"类型`IO t`".所以`main = getLine`是一个有效的(无用的)程序.这与peterwkc的问题完全无关,但当我遇到它时,这是一个有趣的小事实让我感到惊讶. (2认同)