繁体   English   中英

Haskell:理解bind和>>函数

[英]Haskell: Understanding the bind and >> functions

我有以下Haskell表达式:

a = getLine >>= putStrLn . filter isDigit >> a

我无法理解上述表达式的工作原理。 我知道>>=函数采用monadic值和函数(采用正常值并返回monadic值),并返回monadic值。

我知道getLineputStrLn具有以下类型声明:

getLine :: IO String 
putStrLn :: String -> IO ()

所以表达的以下部分:

a = getLine >>= putStrLn . filter isDigit

会返回一个IO () 但是,函数>>取第一个monadic值和第二个monadic值并返回第二个monadic值。

给定原始表达式,传递给>>的第一个参数将是IO String类型。 第二个参数是a

我的问题是, a的类型是什么,以及上述表达式如何继续用户输入并仅将输入的数字部分打印回屏幕? 任何见解都表示赞赏。

注意 :我按照readPrintLoop建议将a函数重readPrintLoopreadPrintLoop ,因为这样可以避免一些混淆。

我的问题是, readPrintLoop的类型是readPrintLoop ,以及上述表达式如何工作以持续获取用户输入并仅将输入的数字部分打印回屏幕?

readPrintLoop类型为: readPrintLoop :: IO a所以它是一个IO a可以是任何类型,因为我们永远不会“返回”那个值,我们永远不会结束这个功能。

该函数不断重复,因为readPrintLoop是根据自身定义的。 readPrintLoop定义为:

readPrintLoop :: IO a
readPrintLoop = getLine >>= putStrLn . filter isDigit >> readPrintLoop

因此,我们在这里有无限递归,因为最终你会遇到a ,然后用另一个getLine >>= putStrLn . filter isDigit >> a替换它getLine >>= putStrLn . filter isDigit >> a getLine >>= putStrLn . filter isDigit >> a等等。

但是,函数>>取第一个monadic值和第二个monadic值并返回第二个monadic值。

(>>)相当于:

(>>) :: Monad m => m a -> m b -> m b
u >> v = u >>= (\_ -> v)

所以执行a等同于:

readPrintLoop :: IO a
readPrintLoop = getLine >>= putStrLn . filter isDigit >>= \_ -> readPrintLoop

这里的下划线变量_将被传递()

a  =  getLine >>= putStrLn . filter isDigit

不是 “表达的一部分”。

      getLine >>= putStrLn . filter isDigit

是表达的一部分。 并且它不会“ 返回 IO () ”。 具有类型IO () (您已正确推断(*) )。 你所谈论的“一元价值”

给它一个名字, 任何名字

ioAction :: IO ()
ioAction  =  getLine >>= (putStrLn . filter isDigit)

我们最终得到了

a  =  ioAction >> a 
----------------------------------
 (>>)     :: IO a -> IO b -> IO b
 ioAction :: IO ()
 a        ::         IO b
----------------------------------
 a        ::                 IO b

以及所有的东西。

a in的语义

a  =  ((>>) ioAction) a

>>的语义定义。


(*)

---------------------------------------------------- 
    (>>=)                     :: 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.

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