2015-01-07 29 views
-1

我開始學習Haskell。儘管我非常笨拙,但我正在努力完成這項工作。我收到的錯誤被列爲標題。這是我編寫的代碼,用於實現複製列表(n)次並將新長度連接爲新列表的行爲。現在我對Haskell中的解析工作有了基本的瞭解,在我的原始代碼下面,我將舉例說明一些修改後的代碼,以瞭解我對解析的理解是否足夠。我現在的問題是我如何正確地縮進或構建我的塊,以便不會收到此錯誤(是否足夠具體:O) - 在創建實例和格式時是否存在一條信息?如果您發現我的當前實例或主要功能是明顯錯誤,請不要提出或提供建議。我想弄清楚它,並在我接觸到它時處理那個GHC錯誤。 (我希望這是學習的正確方法)。但是如果我可以請求任何人幫助我們理解正確格式化的第一個障礙,我將不勝感激。解析錯誤:(不正確的縮進或錯位的括號)

module Main where 
import Data.List 

n :: Int 
x :: [Char] 

instance Data stutter n x where 
    x = [] 
    n = replicate >>= x : (n:xs) 
    stutter >>= main = concat [x:xs] 

let stutter 6 "Iwannabehere" -- <-- parse error occurs here!!! 

- 帶有適當括號的修改代碼,至少在我認爲他們去的地方。

module Main where 
import Data.List 

n :: Int 
x :: [Char] 

instance Data stutter n x where{ 
    ;x = [] 
    ;n = replicate >>= x : (n:xs) 
    ;stutter >>= main = concat [x:xs] 
; 
};let stutter 6 "Iwannabehere" -- there should be no bracket of any kind at the end of this 

我置於塊外的「讓」的表情,我不相信它走了進去,如果我這樣做,我也收到解析錯誤。不正確,但我想我會問。

+3

這段代碼有很多問題。類型簽名需要緊跟定義,所以'n :: Int'後面跟着'x'的簽名是無效的。其次,在此範圍內,聲明一個「實例數據」但「數據」不是一個類型類。第三,頂層聲明不能是表達式,這意味着'let'不是一個有效的頂層構造。也許你應該嘗試閱讀「LYAH」並且一次提出一個問題並建立起來。 –

+2

@ ThomasM.DuBuisson'n :: Int'緊跟着'x :: Int'是完全有效的 - 定義必須位於同一個文件中,但它們並不要求它們與簽名直接相鄰。 – Cubic

+1

'let variable = value'只適用於GHCi和'do'-blocks。你只需要寫'variable = value'。要詳細瞭解與Haskell有關的所有信息,我建議訪問http://learnyouahaskell.com/chapters。 – AJFarmar

回答

5

我不確定instance Data stutter n x應該是什麼,instance XYZ where語法僅用於類型類,但這裏有幾個語法錯誤。

首先,雖然GHC說錯誤在let stutter 6 "Iwannabehere"上,但您的第一個錯誤發生在stutter >>= main = concat [x:xs]之前。一個=標誌被保留用於分配,這僅僅是定義。您可以在頂層,where塊或let塊(where包含類型實例定義)內部進行賦值。您不能將任務指定爲表達式的一部分,例如x >>= y = z

您的下一個語法錯誤是let本身。 let塊不能出現在頂層,它們只出現在另一個定義中。您在GHCi中使用let,但其原因超出了本答案的範圍。只要說在GHCi中輸入表達式不等於源文件的頂層。

接下來,如果您要在某處使用let塊,則它只能包含定義。語法看起來更像

let <name> [<args>] = <definition> 
    [<name> [<args>] = <definition>] 
in <expression> 

而這整個塊做一個表達式。例如,你可以寫

def f(x, y, z): 
    w = x + y + z 
    u = x - y - z 
    return w * u 
在Python

,這將等同於Haskell的函數定義

f x y z = let w = x + y + z 
       u = x - y - z 
      in w * u 

它只定義局部變量。還有,當你使用它裏面do塊,你可以排除in <expression>部分,如

main = do 
    name <- getLine 
    let message = if length name > 5 then "short name" else "long name" 
     goodbye n = putStrLn ("Goodbye, " ++ n) 
    putStrLn message 
    goodbye name 

注意,沒有必要在這裏使用in另一種形式。你可以,如果你想,它只是意味着你要開始一個新的do塊:

main = do 
    name <- getLine 
    let message = ... 
     goodbye n = ... 
    in do 
     putStrLn message 
     goodbye name 

這是不是漂亮。

希望這可以讓你更加傾向於正確的語法,但看起來你對Haskell的工作原理有一些誤解。你有沒有看過學習你一個Haskell?這是一門非常溫和而有趣的語言介紹,可以幫助您學習語法和核心思想。

+0

bheklir,無非是尊重你。即使我吸吮,你也是我渴望成爲的那種類型的哈斯克勒。我看了一下並且閱讀了學習你一個Haskell。感謝您用「let」的句法正確的定義指引我走向正確的方向。我還有很多事情要跟上,我不知道我爲什麼不「得到它」。我很傷心,這不能成爲我全職工作的焦點。再次感謝。 – dgomez1092

+0

@ dgomez1092大約6年前,我第一次見到Haskell。我用這種語言捅了一會兒,但在大部分的大學裏都放棄了。實習期間我有一段緩慢的時間,我回到了它。經過幾個月的努力,我終於認爲自己已經「得到了它」。幾年之後,我仍然不確定我是否完成了。對許多人來說,Haskell是一種奇怪而困難的語言,但它值得堅持下去!這不是你吮吸,只是你需要更多的練習。只要繼續提問,繼續練習,這些作品就會開始落實。 – bheklilr

1

您的分析錯誤來自於let關鍵字。將其刪除並且不會發生與此相關的錯誤。 let x = y只與GHCi和do -blocks有關,在這一點上都不相關。本質上,只是這一行替換它:

theWordIGet = stutter 6 "Iwannabehere" 

其次,在Haskell instance關鍵字absolutley無關做你想要在這個階段做什麼。這不是如何定義Haskell函數的,這是我猜你想要做的。這是你想要創建一個stutter函數,假設它只是重複一個字符串n次。

stutter :: Int -> String -> String 
stutter n x = concat (replicate n x) 

您也想刪除的類型聲明的(外的範圍)值nx:他們不是對象,他們是一個函數,它有自己的簽名參數確定函數調用中的nx的類型。

最後,我想你會想要在程序執行時打印stutter 6 "Iwannabehere"的值。要做到這一點,只是補充一點:

main :: IO() 
main = print (stutter 6 "Iwannabehere") 

最後,我懇請要從頭開始讀「學習你Haskell的」網上here,因爲你在完全錯誤的方向前進關 - 你引用的程序是一堆表達式,可能有意義,但完全在錯誤的地方。本書將向你展示Haskell的語法,我可以在這個答案中寫得更好,並且會完全解釋如何讓你的程序按照你期望的方式運行。

相關問題