簡體   English   中英

Haskell中的“ do”構造

[英]'do' construct in Haskell

我正在嘗試學習Haskell,並想編寫一個小程序,將文件的內容打印到屏幕上。 將其加載到GHCi中時,出現以下錯誤:

“ do”構造中的最后一條語句必須是表達式

我知道這個問題已經在這里被問到了: Haskell —“'do'構造中的最后一個語句必須是一個表達式”

即使我的代碼非常相似,我仍然無法找出問題所在。 如果有人可以向我指出問題,我將非常感激。

module Main (main) where

import System.IO
import System(getArgs)

main :: IO()
main = do
    args <- getArgs
    inh <- openFile $ ReadMode head args
    printFile inh
    hClose inh

printFile :: Handle -> IO ()
printFile handle = do
    end <- hIsEOF handle
        if end
            then return ()
            else do line <- hGetLine handle
                putStrLn line
                printFile handle

您的縮進已損壞。 這些更好:

printFile :: Handle -> IO ()
printFile handle = do
    end <- hIsEOF handle
    if end
        then return ()
        else do line <- hGetLine handle
                putStrLn line
                printFile handle

printFile :: Handle -> IO ()
printFile handle = do
    end <- hIsEOF handle
    if end
        then return ()
        else do
            line <- hGetLine handle
            putStrLn line
            printFile handle

通過縮進( ifend <- hIsEof handle更縮進),實際上是行的延續,而不是do的后續操作。 同樣, putStrLn lineline <- hGetLine handle縮進的事實意味着do (在else )到此結束。

有一些問題。 首先,將if縮進得太遠end <- ...假定為do的最后一行。 不確定...

下一個問題來了。 相同的錯誤消息,僅在第18行。這次,第19行和第20行的縮進不夠深(它們沒有作為do一部分進行解析)。 縮進(無論如何看起來都更好,因為它現在全部都對齊了)...下一條錯誤消息。 好消息是,這不是一次縮進錯誤,並且修復程序也變得微不足道了。

test.hs:9:22:
    Couldn't match expected type `([a] -> a) -> [String] -> FilePath'
           against inferred type `IOMode'
    In the second argument of `($)', namely `ReadMode head args'
    In a stmt of a 'do' expression:
        inh <- openFile $ ReadMode head args
    In the expression:
        do { args <- getArgs;
             inh <- openFile $ ReadMode head args;
             printFile inh;
             hClose inh }

解決方法是inh <- openFile (head args) ReadMode 如果您想更詳細地說明版本不正確的原因/方式或錯誤的含義,請告訴我,我將進行編輯。

你這樣寫:

main :: IO()
main = do
    args <- getArgs
    inh <- openFile $ ReadMode head args
    printFile inh
    hClose inh

但這可能更好:

main :: IO()
main = do
    args <- getArgs
    withFile (head args) ReadMode printFile

您始終可以將顯式括號與{ ; } { ; }永遠不必擔心這個空白愚蠢。

printFile :: Handle -> IO ()
printFile handle = do {
    end <- hIsEOF handle ;
        if end
            then return ()
            else do { line <- hGetLine handle ;
                putStrLn line ;
                printFile handle }}

本來會很好(例如,不會導致錯誤)。

在Haskell中,通過特殊的“ do ”語言來處理I / O。 應該接受它。 它實際上是通過monad實現的是實現細節。

需要說明的是:我認為大括號不是更好,我認為它們應該與優美而一致的縮進一起使用。 花括號為我們提供了有關代碼結構的直觀,直觀的線索。 當然,在大多數情況下,瘋狂的縮進毫無意義。 而且,花括號為我們提供了工作代碼的保證,並使我們免於對空白事故的毫無意義的擔心。 他們消除了這種脆性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM