Haskell:做块,最后一个语句必须是表达式

Haskell: Do block, last statement must be expression

我想知道右击或左击按钮时的区别。我写了下面的代码:

import Graphics.UI.Gtk
import Control.Monad.IO.Class 

--main::IO()
main = do
    initGUI

window <- windowNew

    button <- buttonNewWithLabel "button"

    on button buttonPressEvent (tryEvent (do button <- eventButton

                                             liftIO (extrafunctie button)
                                             ))                                         
    containerAdd window button

    onDestroy window mainQuit

    widgetShowAll window

    mainGUI

extrafunctie b = if (RightButton == b) 
                 then putStrLn "True"
                 else putStrLn "False"

我收到以下错误:

jolien@jolien-VirtualBox:~/Documenten/haskell$ ghc --make test.hs -o test
[1 of 1] Compiling Main             ( test.hs, test.o )

test.hs:9:50:
    The last statement in a 'do' block must be an expression
      button <- eventButton liftIO (extrafunctie button)

我查看了我的缩进,这是正确的。有人知道解决方案吗?

下面怎么样?

import Graphics.UI.Gtk
import Control.Monad.IO.Class 

--main::IO()
main = do
  initGUI
  window <- windowNew
  button <- buttonNewWithLabel "button"
  on button buttonPressEvent (tryEvent (do button <- eventButton
                                         liftIO (extrafunctie button)
                                         ))                                      
  containerAdd window button
  onDestroy window mainQuit
  widgetShowAll window
  mainGUI

extrafunctie b = if (RightButton == b) 
           then putStrLn "True"
           else putStrLn "False"

你的缩进太糟糕了,这就是问题所在。你需要替换这个:

on button buttonPressEvent (tryEvent (do button <- eventButton

                                         liftIO (extrafunctie button)
                                         ))  

与:

on button buttonPressEvent $
    tryEvent $ do 
        button <- eventButton
        liftIO (extrafunctie button)

您也可以将 extrafunctie 函数替换为:

extrafunctie b = print (RightButton == b)

以下是编译器如何查看您的代码,制表符以 8 个字符为间隔。 我会将制表符显示为 -------|,将空格显示为 .:

>....import Graphics.UI.Gtk
>....import Control.Monad.IO.Class 
>
>....--main::IO()
>....main = do
>....-|initGUI

>...--|window <- windowNew

>....-|button <- buttonNewWithLabel "button"

>....-|on button buttonPressEvent (tryEvent (do button <- eventButton

>....-|------|------|------|------|------|------|------|------|------|..----|.liftIO (extrafunctie button)
>....-|------|------|------|------|------|------|------|------|------|.....))                                           
>....-|containerAdd window button

>....-|onDestroy window mainQuit

>....-|widgetShowAll window

>....-|mainGUI
>
>....extrafunctie b = if (RightButton == b) 
>....-|------|------|------|.then putStrLn "True"
>....-|------|------|------|.else putStrLn "False"

如您所见,编译器将 liftIO (extrafunctie 位视为更靠右的位置。 如果您使用空格来布置您的工作,则不会发生这种情况:

>    import Graphics.UI.Gtk
>    import Control.Monad.IO.Class 
>
>    --main::IO()
>    main = do
>      initGUI
>      window <- windowNew
>      button <- buttonNewWithLabel "button"
>      on button buttonPressEvent (tryEvent (do button <- eventButton
>                                               liftIO (extrafunctie button)
>                                               ))                                             
>      containerAdd window button
>      onDestroy window mainQuit
>      widgetShowAll window
>      mainGUI
>
>    extrafunctie b = if (RightButton == b) 
>                  then putStrLn "True"
>                  else putStrLn "False"

如果你坚持使用空格,这是最简单的。更改编辑器的设置。

如果您只使用空格而不使用任何制表符,则不会出现此问题,因为您的编辑器必须按照编译器的考虑方式显示它。

我的编辑器让我指定当我按下制表符时,它应该插入一个制表符将显示的空格数,所以我使用它,这对于 4 个制表位是安全的。如果你的编辑器可以做到这一点, 使用该选项。 (如果没有,请考虑在编程时使用更聪明的编辑器。)

我的编辑器也有自动缩进和取消缩进功能,下一行复制上一行的空白缩进——这避免了这个问题。如果您的编辑器支持它,请打开它,因为它可以节省您的精力并且您不太可能遇到解析错误。 (当我然后按退格键时,我的编辑器会删除回之前的缩进级别,这很好。)

几乎所有编辑器都可以更改选项卡的显示方式。如果你不能让它为制表符使用空格,你应该将 tabstop 更改为 8,因为这与 ghc 匹配,并且你不太可能得到这个错误,但你最好还是使用空格。