我正在學習 Haskell,作為練習,我被要求撰寫一個函式,該函式nextlet回傳指定引數(一個字符)之后的下一個字母。規范說假設'a'跟隨'z'并且'A'跟隨'Z',并且我做出了一個執行決定,對A到Z和a到z范圍之外的字符呼叫函式回傳''。
我的第一次嘗試是:
nextlet c | c == 'Z' = 'A'
| c == 'z' = 'a'
| c `elem` ['A'..'Y'] = succ c
| c `elem` ['a'..'y'] = succ c
| otherwise = ' '
這行得通。
但是,我后來認為不必重復處理大寫和小寫會很好,所以我發現了如何將字符轉換為大寫,并編碼:
nextlet c | c == 'Z' = 'A'
| c `elem` ['A'..'Y'] = succ c
| c `elem` ['a'..'z'] = nextlet toUpper c
| otherwise = ' '
編譯失敗,出現錯誤訊息“變數不在范圍內:toUpper :: Char”;這很有意義,因為我沒有匯入Data.Char.
但是當我包含import Data.Char在我的腳本頂部時,它仍然無法編譯。函式定義的第一行失敗了
Couldn't match type ‘Char’ with ‘Char -> Char’
Expected type: (Char -> Char) -> Char -> Char
Actual type: Char -> Char
nextlet c | c == 'Z' = 'A'
^^^^^^^^^^^^^^^^^^^^^^^^^^
這有什么問題,為什么匯入Data.Char之前成功時會導致編譯失敗?
uj5u.com熱心網友回復:
你應該使用nextlet (toUpper c),否則你作為引數傳遞toUpper,這是一個函式Char -> Char,而不是一個Char。
因此,您將其實作為:
nextlet c | c == 'Z' = 'A'
| c `elem` ['A'..'Y'] = succ c
| c `elem` ['a'..'z'] = nextlet (toUpper c)
| otherwise = ' '
uj5u.com熱心網友回復:
Willem Van Onsem 的回答解釋了如何解決您的問題,但沒有解釋為什么編譯器的行為似乎發生了變化。GHC 有多個通行證。在這種情況下,兩個重要的是重命名器和型別檢查器。當您使用無法決議的名稱時,重命名器將失敗并且編譯停止,因此即使您有型別錯誤,您也不會看到任何型別錯誤。當您通過 import 決議名稱時Data.Char,您發現了一個一直存在的型別錯誤。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/412900.html
標籤:
上一篇:Haskell中的基本函子
