Haskell输入返回元组 [英] Haskell Input Return Tuple
问题描述
我想知道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 - >一个
,那么我们希望它是不可能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屋!