[英]Haskell: Understanding the bind and >> functions
I have the following Haskell expression: 我有以下Haskell表达式:
a = getLine >>= putStrLn . filter isDigit >> a
I am having trouble understanding how the above expression works. 我无法理解上述表达式的工作原理。 I know the
>>=
function takes a monadic value and a function (that takes a normal value and returns a monadic value), and returns a monadic value. 我知道
>>=
函数采用monadic值和函数(采用正常值并返回monadic值),并返回monadic值。
I know that getLine
and putStrLn
have the following type declarations: 我知道
getLine
和putStrLn
具有以下类型声明:
getLine :: IO String
putStrLn :: String -> IO ()
So the following part of expression: 所以表达的以下部分:
a = getLine >>= putStrLn . filter isDigit
Would return an IO ()
. 会返回一个
IO ()
。 However, the function >>
takes a first monadic value and a second monadic value and returns the second monadic value. 但是,函数
>>
取第一个monadic值和第二个monadic值并返回第二个monadic值。
Given the original expression, the first argument passed to >>
would be of type IO String
. 给定原始表达式,传递给
>>
的第一个参数将是IO String
类型。 The second argument is a
. 第二个参数是
a
。
My question is, what is the type of a
, and how does the above expression work to continually take user input and print only the numeric part of the input back to the screen? 我的问题是,
a
的类型是什么,以及上述表达式如何继续用户输入并仅将输入的数字部分打印回屏幕? Any insights are appreciated. 任何见解都表示赞赏。
Note : I renamed the a
function to readPrintLoop
as suggested by @SamuelBarr , since that avoids some confusion. 注意 :我按照
readPrintLoop
建议将a
函数重readPrintLoop
为readPrintLoop ,因为这样可以避免一些混淆。
My question is, what is the type of
readPrintLoop
, and how does the above expression work to continually take user input and print only the numeric part of the input back to the screen?我的问题是,
readPrintLoop
的类型是readPrintLoop
,以及上述表达式如何工作以持续获取用户输入并仅将输入的数字部分打印回屏幕?
readPrintLoop
has type: readPrintLoop ::
so it is an IO a
IO
. readPrintLoop
类型为: readPrintLoop :: IO a
所以它是一个IO
。 The a
can be any type, since we never "return" that value, we will never end this function. a
可以是任何类型,因为我们永远不会“返回”那个值,我们永远不会结束这个功能。
The function is constantly repeated because readPrintLoop
is defined in terms of itself. 该函数不断重复,因为
readPrintLoop
是根据自身定义的。 readPrintLoop
is defined as: readPrintLoop
定义为:
readPrintLoop :: IO a
readPrintLoop = getLine >>= putStrLn . filter isDigit >>
readPrintLoop
We here thus have infinite recursion, since eventually you will run into a
, and thus replace that with another getLine >>= putStrLn . filter isDigit >> a
因此,我们在这里有无限递归,因为最终你会遇到
a
,然后用另一个getLine >>= putStrLn . filter isDigit >> a
替换它getLine >>= putStrLn . filter isDigit >> a
getLine >>= putStrLn . filter isDigit >> a
and so on. getLine >>= putStrLn . filter isDigit >> a
等等。
However, the function
>>
takes a first monadic value and a second monadic value and returns the second monadic value.但是,函数
>>
取第一个monadic值和第二个monadic值并返回第二个monadic值。
(>>)
is equivalent to: (>>)
相当于:
(>>) :: Monad m => m a -> m b -> m b
u >> v = u >>= (\_ -> v)
so the implementation of a
is equivalent to: 所以执行
a
等同于:
readPrintLoop :: IO a
readPrintLoop = getLine >>= putStrLn . filter isDigit >>= \_ ->
readPrintLoop
Here the underscore variable _
will be passed ()
. 这里的下划线变量
_
将被传递()
。
a = getLine >>= putStrLn . filter isDigit
is not "the part of expression". 不是 “表达的一部分”。
getLine >>= putStrLn . filter isDigit
is the part of the expression. 是表达的一部分。 And it does not " return
IO ()
". 并且它不会“ 返回
IO ()
”。 It has the type IO ()
(which you've correctly inferred (*) ). 它具有类型
IO ()
(您已正确推断(*) )。 It is a "monadic value" that you talk about. 这是你所谈论的“一元价值” 。
Giving it a name, any name , 给它一个名字, 任何名字 ,
ioAction :: IO ()
ioAction = getLine >>= (putStrLn . filter isDigit)
we end up with 我们最终得到了
a = ioAction >> a
----------------------------------
(>>) :: IO a -> IO b -> IO b
ioAction :: IO ()
a :: IO b
----------------------------------
a :: IO b
and everything typechecks. 以及所有的东西。
The semantics of a
in a
in的语义
a = ((>>) ioAction) a
is defined by the semantics of >>
. 由
>>
的语义定义。
(*) (*)
----------------------------------------------------
(>>=) :: m a -> (a -> m b) -> m b
getLine :: IO String m a
putStrLn :: String -> IO ()
putStrLn . filter isDigit :: String -> IO () a -> m b
---------------------------------------------------- ------------
getLine >>= (putStrLn . filter isDigit) :: IO () m b
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.