2013-04-03 65 views
1

我想寫得到多個字符串輸入,並終止在一個空行(「\ n」)的函數我有以下Haskell- IO字符串獲得多行

getLines :: IO [String] 
getLines = do x <- getLine 
      if x == "" 
      return() 
      else do xs <- getLines 
       return (x:xs) 

失敗編譯說有有毛病的if語句

理想我想對這樣的

getLines工作

蘋果

(進入被按下)

輸出: [ 「蘋果」, 「鳥」, 「貓」]

回答

6

if()(空元組)應該是[](空列表)之後,您需要then。在if中,thenelse需要縮進,因爲if then else是一個運算符,編譯器需要知道表達式是否繼續。你的壓痕需要進行調整,以使所有東西都要縮比領先do更多:

getLines :: IO [String] 
getLines = do x <- getLine 
       if x == "" 
       then return [] 
       else do xs <- getLines 
         return (x:xs) 

或者一切都縮進超過包含領先do

getLines :: IO [String] 
getLines = do 
    x <- getLine 
    if x == "" 
    then return [] 
    else do 
     xs <- getLines 
     return (x:xs) 

作爲的問題樣式,您也可以使用null x而不是x == ""

+0

謝謝!它現在有效! – lopezrican304 2013-04-03 21:26:51

+1

'(x :) <$> getLines'也是可能的。根據定義,這不是更好,但在這種情況下,我更喜歡它比'做'符號。需要'輸入Control.Applicative((<$>))',但。 – 2013-04-04 00:51:44

+1

@Zoidberg:是的,我通常更喜歡應用風格,但不想過度改變這個例子。它也可以寫成'getLines = untilNull getLine',其中'untilNull'被定義爲無空格且無空格爲'execWriterT.fix.ap(liftM(= <<)(ap(unless.null).ap(liftM(>>) (tell。(:[])))。const))。const.lift'與適當的導入。 – 2013-04-04 02:53:51

1

這幾乎是正確的。

您需要一個then在您的if之後。您可能還需要稍微更改縮進,以便所有內容都縮進到x而不是do。我認爲這應該做的。

+1

它現在也不會檢測,我認爲'return()'應該是'return []'。 '[]'是一個空列表,'()'是單元。 – DarkOtter 2013-04-03 21:06:52

+0

@DarkOtter是的 - 好的工作! – MathematicalOrchid 2013-04-04 07:37:04