与Haskell混淆阻塞

hou*_*oft 3 monads haskell

我有以下代码:

doSomething :: [Int] -> [Int]
doSomething arg = arg ++ [1]

afterThreeTurns = do
    first <- ["test"]
    doSomething [1] -- COMMENT THIS
    return first
Run Code Online (Sandbox Code Playgroud)

返回:

*Main> afterThreeTurns
["test","test"]
Run Code Online (Sandbox Code Playgroud)

如果我拿出标记为COMMENT THIS的行,则按预期返回["test"].为什么?我看待它的方式做什么应该先没有效果?

Eri*_*ikR 6

因为doSomething [1]就是[2,1],你的代码就相当于:

afterThreeTurns = do
   first <- ["test"]
   x <- [2,1]
   return first
Run Code Online (Sandbox Code Playgroud)

这与列表理解相同,[ first | first <- ["test"], x <- [2,1] ]后者解释了为什么要获得长度为2的列表.

请注意,该变量x未在任何地方引用,因此也可以这样写:

afterThreeTurns = do
   first <- ["test"]
   _ <- [2,1]
   return first
Run Code Online (Sandbox Code Playgroud)

这是使用IOmonad 的类似情况.代码:

thirdLine = do
  getLine
  getLine
  x <- getLine
  putStrLn $ "The third line is: " ++ x
Run Code Online (Sandbox Code Playgroud)

是相同的:

thirdLine = do
  _ <- getLine
  _ <- getLine
  x <- getLine
  putStrLn $ "The third line is: " ++ x
Run Code Online (Sandbox Code Playgroud)

您可以使用-fwarn-unused-do-bind编译器标志来获取ghc以标记这些类型的monadic语句 .在您的示例中,ghc将发出警告:

...: Warning:
    A do-notation statement discarded a result of type ‘Int’
    Suppress this warning by saying ‘_ <- doSomething [1]’
    or by using the flag -fno-warn-unused-do-bind
Run Code Online (Sandbox Code Playgroud)