2012-10-16 37 views
3

我嘗試寫這需要一個數組和遍歷它的自定義函數返回,我需要打印每一個數字和遞歸推出相同的功能,但我得到的錯誤哈斯克爾,如何打印價值和功能

解析錯誤輸入'主

代碼:

firstitem n = if n /= [] n firstitem(tail n) 


main = do 
    print(firstitem [1,2,3]) 
+0

我的問題有什麼不好?它完全定義。 – testCoder

+2

我認爲在這個問題上*無法解釋的*降低了有點苛刻。 –

+0

這個問題顯示了對Haskell基本概念的完全無知(在打印某個函數時沒有IO monad的跡象;對haskell的if-then-else語法和語義無知),而且缺乏常識:如果你想要要遞歸地打印某些東西,你需要將'print'放入遞歸函數中(即使對命令式程序員來說它也應該是顯而易見的)。 –

回答

11

您的第一個問題是您的語句錯誤if。你應該寫

firstItem n = if {- condition-} 
    then {- do this -} 
    else {- do that -} 

二,什麼功能firstItem應該做的事,目前還不清楚。這聽起來像是它應該返回列表的第一項,但是您的描述看起來好像您要遍歷列表中的所有元素。

可以迭代和打印合併成一個單一的功能是這樣的:

printAll xs = if null xs  -- If the list is empty 
    then return()    -- then we're done, so we quit. 
    else do print (head xs)  -- Otherwise, print the first element 
      printAll (tail xs) -- then print all the other elements. 

main = printAll [1,2,3] 

功能null返回True如果列表爲空,否則返回False。語句return()可以認爲是「沒有更多要處理的,所以現在停止該功能並返回任何結果」。第三行和第四行包含一個「do block」。 do塊基本上是一個膠水,它將兩個動作print (head xs)printAll (tail xs)合併爲一個動作。你可以用花括號寫它,使它更清楚一點:

do { 
    print (head xs); 
    printAll (tail xs) 
} 

雖然你實際上並不需要他們 - 壓痕指定你的意思。

這解決了你的問題,但它有點笨重。畢竟Haskell應該是一門美麗的語言 - 所以我們讓你的代碼變得美麗!使用模式匹配將列表拖入其頭部和尾部會更好:

printAll []  = return() 
printAll (x:xs) = do print x 
        printAll xs 

這樣會好很多。但它可能更加模塊化。嘿,也許我們可以做一個通用的函數,它的動作作爲輸入,並執行該行動列表的每一個元素:

repeatedly f []  = return() 
repeatedly f (x:xs) = do f x 
         repeatedly f xs 

printAll xs = repeatedly print xs 

這很好。但實際上,已經有一個功能可以做到這一點。這就是所謂的mapM_(有一個很好的理由,它被稱爲這一點,但我不會進入現在)和它的Control.Monad模塊:

import Control.Monad 

printAll xs = mapM_ print xs 

其實,你可以不用輸入這些xs參數,編譯器可以推斷它應該在那裏:

printAll = mapM_ print 

最後,你的代碼很漂亮。希望有點幫助。

+0

非常感謝,非常詳細的解釋! – testCoder

+0

「Control.Monad」的信息豐富和極好的介紹 –

1

在Haskell的if總是需要有一個else分支以及。您還錯過了then,即您需要的形式爲if CONDITION then TRUE_VAL else FALSE_VAL

通過使用模式匹配,您可以完全避免if

要在執行過程中打印出進度,您可以使用Writer monad

+0

我不需要在「其他」語句中做什麼,我該怎麼辦? – testCoder

+0

'else'分支也需要一個值。而且,「第一項(尾n)」應該是什麼樣的價值呢?就像那是錯的。 –

+0

我需要打印(返回)n值並遞歸調用相同的函數,該如何實現? – testCoder