Haskell输入返回元组 [英] Haskell Input Return Tuple

查看:181
本文介绍了Haskell输入返回元组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道IO()函数是否可以返回元组,因为我希望将这些函数作为另一个函数的输入使用。



pre $ lt; code> investinput :: IO() - >([Char],Int)
investinput = do
putStrLn输入用户名:
用户名< - getLine

putStrLn输入投资金额:
tempamount< - getLine
let amount = show temp安装
return(用户名,金额)

请帮助。

谢谢。

解决方案

在Haskell中,IO不像你习惯的语言那样工作。 Haskell中的所有函数都必须是纯的:即,如果使用参数 x 调用函数 f ,则必须把它称为一次,两次或一百次都没有区别。不过,考虑这对于IO意味着什么。简单地说, getLine 应该有类型 getLine :: String ,或者 getLine ::( ) - >串。 (()是单元类型,它的唯一值是();它有点像一个void类型类似C的语言,但是它有一个单一的值。)但是这意味着每次你写 getLine 时,它必须返回相同的字符串,这不是你想要的。这是 IO 类型的目的:封装动作。这些行为不同于功能;它们代表不纯的计算(虽然它们本身是纯的)。类型 IO a 的值表示一个动作,该动作在执行时返回类型为 a 的值。因此, getLine 具有类型 getLine :: IO String :每次评估操作时,生成字符串(通过读取用户)。类似地, putStr 的类型为 putStr :: String - > IO();它是一个函数,它接受一个字符串并返回一个动作,该动作在运行时不会返回有用的信息......但是,作为一种副作用,可以在屏幕上打印出一些东西。



您正试图编写一个类型为 IO() - >的函数。 ([Char],Int)。这将是一个函数,它将输入一个动作并返回一个元组,它不是你想要的元素。你需要一个 IO(String,Int) - 一个动作,它在运行时产生一个由字符串组成的元组(这是 [ Char] )和一个整数。你现在的代码也快到了!这是你需要改为:

  investinput :: IO(String,Int)
investinput = do
putStrLn输入用户名:
用户名< - getLine
putStrLn输入投资金额:
tempamount< - getLine
let amount =读取tempamount
返回(用户名,金额)

请注意,我只做了两项更改(并删除了一个空白线)。首先,我改变了函数的类型,就像我上面所说的那样。其次,我将 show 更改为 read show 函数的类型为 Show a => a - > String :它是一个函数,它接受任何可以显示的内容并生成一个代表它的字符串。 阅读,其类型为阅读a =>字符串 - >一个:给出一个字符串,它解析它并返回一些可读的值。



另外一个问题是返回一个元组(String,Int)而不是动作 IO(String,Int)。没有纯粹的方法来做到这一点;换句话说,没有纯函数 IO a - >>一个。为什么是这样?因为 IO a 表示一种不纯的行为,它取决于现实世界。如果我们有这样一个函数 impossibleRunIO :: IO a - >一个,那么我们希望它是 impossibleRunIO getLine == impossibleRunIO getLine 的情况,因为函数必须是纯的。但是这是无用的,因为我们希望不可能RUNIO 能够真正与真实世界交互!因此,这种纯粹的功能是不可能的。所有进入 IO 的东西都不能离开。这就是 return 的作用:它是一个函数,在这种情况下是 1 ,类型 return :: a - > IO a ,它使您可以将纯数值放入 IO 中。对于任何 x return x 是一个动作,它在运行时始终产生 x 。这就是为什么你必须用 return 用户名来结束 do c $ c>是从动作中提取的纯粹值,因此只能在 do 块中可见。在外界看到它之前,你需要把它放到 IO 中。 金额 / tempamount

同样如此。

为了完整起见,背后有一些总体理论将它联系在一起。但开始Haskell编程并不是必需的。我推荐的做法是将大部分代码组织为折叠,旋转和破坏数据的纯函数。然后构建一个与前述函数交互的瘦(尽可能瘦) IO 前层。你会很惊讶,你需要多少IO!



1:它实际上有一个更通用的类型,但这一点不相关。 $ b

i wonder can a IO() function return tuple because i would like to get these out of this function as input for another function.

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

 putStrLn "Enter Invest Amount : "
 tempamount <- getLine
 let amount = show  tempamount
 return (username, amount)

Please help.

Thanks.

解决方案

IO in Haskell doesn't work like IO in the languages you're used to. All functions in Haskell must be pure: that is, if a function f is called with the argument x, there must be no difference between calling it once, twice, or a hundred times. Consider what this means for IO, though. Naïvely, getLine should have the type getLine :: String, or perhaps getLine :: () -> String. (() is the unit type, whose only value is (); it's sort of like a void type in a C-like language, but there is a single value of it.) But this would mean that every time you wrote getLine, it would have to return the same string, which is not what you want. This is the purpose of the IO type: to encapsulate actions. These actions are distinct from functions; they represent impure computation (though they themselves are pure). A value of type IO a represents an action which, when executed, returns a value of type a. Thus, getLine has type getLine :: IO String: every time the action is evaluated, a String is produced (by reading from the user). Similarly, putStr has type putStr :: String -> IO (); it is a function which takes a string and returns an action which, when run, returns no useful information… but, as a side effect, prints something to the screen.

You are attempting to write a function of type IO () -> ([Char], Int). This would be a function which took as input an action and returned a tuple, which is not what you want. You want an IO (String, Int)—an action which, when run, produces a tuple consisting of a string (which is a synonym for [Char]) and an integer. You're almost there with your current code, too! This is what you'll need instead:

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

Notice that I've only made two changes (and removed a blank line). First, I've changed the type of the function, like I said above. Second, I changed show into read. The show function has the type Show a => a -> String: it is a function which takes anything which can be shown and produces a string representing it. You wanted read, which has the type Read a => String -> a: given a string, it parses it and returns some readable value.

The other thing you asked about is returning a tuple (String, Int) instead of an action IO (String, Int). There is no pure way to do this; in other words, there is no pure function IO a -> a. Why is this? Because IO a represents an impure action which depends on the real world. If we had such a function impossibleRunIO :: IO a -> a, then we would want it to be the case that impossibleRunIO getLine == impossibleRunIO getLine, since the function must be pure. But this is useless, as we would want impossibleRunIO to be able to actually interact with the real world! Thus, this pure function is impossible. Everything that enters IO can never leave. This is what return does: it is a function with, in this case1, the type return :: a -> IO a, which enables you to place pure values into IO. For any x, return x is an action which, when run, always produces x. This is why you have to end your do block with the return: username is a pure value you extracted from an action, and as such is only visible within the do block. You need to lift it into IO before the outside world can see it. The same is true of amount/tempamount.

And just for completeness's sake: there is some overarching theory behind this which ties it together. But it's not necessary at all for beginning Haskell programming. What I would recommend doing is structuring most of your code as pure functions which fold, spindle, and mutilate your data. Then construct a thin (as thin as possible) IO front layer which interacts with said functions. You'll be surprised how little IO you need!

1: It actually has a more general type, but that's not relevant for the moment.

这篇关于Haskell输入返回元组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆