【发布时间】:2019-07-26 10:17:18
【问题描述】:
我有以下 Haskell 表达式:
a = getLine >>= putStrLn . filter isDigit >> a
我无法理解上述表达式的工作原理。我知道>>= 函数接受一个单子值和一个函数(它接受一个正常值并返回一个单子值),并返回一个单子值。
我知道getLine 和putStrLn 有以下类型声明:
getLine :: IO String
putStrLn :: String -> IO ()
所以下面的部分表达式:
a = getLine >>= putStrLn . filter isDigit
将返回IO ()。但是,函数>> 接受第一个单子值和第二个单子值并返回第二个单子值。
给定原始表达式,传递给>> 的第一个参数将是IO String 类型。第二个参数是a。
我的问题是,a 的类型是什么,上面的表达式如何不断地接受用户输入并仅将输入的数字部分打印回屏幕?任何见解都值得赞赏。
【问题讨论】:
-
a :: IO t。是的,它是多态的。无限计算永远不会返回任何内容,因此它可以是任何类型。 -
如果定义为
a=a(无限递归),则类型为a :: forall b. b,即a可以是任何类型b。因为我们改为使用a = ioAction >> a,所以我们强制b采用IO t的形式,但t可以是任何东西。所以我们得到a :: forall t. IO t。它仍然是无限递归,只是在每次递归调用时都会运行 IO 操作。从某种意义上说,这是可行的,因为>>在执行其第一个参数/动作之前不会评估其第二个参数/动作。 -
用括号括起来,你所拥有的是
a = (getLine >>= (putStrLn . filter isDigit)) >> a。 (>>和>>=都是infixl 1)。 -
您说,“传递给
>>的第一个参数将是IO String类型”。你认为传递给>>的第一个参数是什么?为什么你认为它的类型为IO String? (这不是第一个参数的正确类型,所以如果您解释您的想法,我们可能会帮助您发现其中的错误。)
标签: haskell functional-programming monads io-monad