2014-11-09 25 views
0

您好我有這些功能:如何將值列表中的從存儲if語句

i_am_at::String->String 
i_am_at place = 
    place 

at::String-> (String, String) 
at place = 
    case place of 
    "bedroom" -> ("fly", "light switch") 
    "den" -> ("flyswatter", "light switch") 

main::IO() 
main = do 
    putStrLn "Enter place" 
    p <- getLine :: IO String 
    i_am_at p 

我想編寫一個函數「吃」是需要一個參數「項」並調用返回的i_am_at功能字符串「place」,然後用i_am_at函數返回的字符串調用「at」函數,然後在放置臥室時檢查該項是否爲電燈開關,然後將其存儲到數組中並返回。但是,如果物品是蒼蠅然後不存儲它。同樣,如果place爲den並且該項目來自兩者,則將其存儲到該數組中。我正在做這樣的事情:

take::String->String[],IO() 
take item = 
    plc = i_am_at 
    | plc == "bedroom" && item == "light switch" && item not present in list y already (I don't know how to write this condition) 
     y = item 
    | plc == "bedroom" && item == "fly" && item not present in list y already (I don't know how to write this condition) 
     = putStrLn "You cannot take that" 
    | plc == "den" && item == "flyswatter" && item not present in list y already (I don't know how to write this condition) 
     y = item 
    | plc == "den" && item == "light switch" && item not present in list y already (I don't know how to write this condition) 
     y = item 
    | if item present in list y already 
     = putStrLn "You already have it" 
    | Otherwise = putStrLn "Item is not here" 
    return y 

有人可以幫我修復這個功能。 y是這個函數中的一個列表,但我不知道如何在其中存儲值。我也不知道我們如何獲得返回值並返回值並將其打印出來的返回類型。我也不知道陳述plc=i_am_at是否正確。如何使這項工作?

回答

2

在像Haskell這樣的純函數式語言可以模擬可變狀態與以下幾招:

  1. 定義的數據結構包含可能改變一切(讓我們稱之爲World
  2. 將所有的國家修改函數以獲得簽名World -> World(或者,如果您需要執行IO,則可能需要World -> IO World該函數從現有函數創建新的世界值
  3. 將所有函數調用鏈接起來,以便傳遞一個調用的輸出世界作爲中提供下一個功能。

例子:比方說,你的世界只包含一個項目的列表(字符串):

type World = [String] 

要刪除一個項目,你會寫這樣一個功能:

removeItem :: String -> World -> IO World 
removeItem item world = do 
    if elem item world 
    then do putStrLn "Item removed." 
      return $ delete item world 
    else do putStrLn "No such item - " ++ item 
      return world 

然後你可以刪除兩項:

removeTwoItems a b world = do 
    world1 <- removeItem a world 
    world2 <- removeItem b world 
    return world2 

有先進的機械nisms(例如State monad)可以幫助您處理這些模式,但實質上這是發生了什麼。

一個更完整的例子展示瞭如何這種模式集成到應用程序:

look :: World -> IO World 
look w = do 
    putStrLn $ "You see these items here: " ++ show w 
    return w 

loop w = do 
    words <- fmap words getLine 
    case words of 
    ("quit":_) -> return() 
    ("look":_) -> do w' <- look; loop w' 
    ("remove":item:_) -> do w' <- removeItem item w; loop w' 
    _ -> do putStrLn "huh?"; loop w 

main = do 
    let world0 = ["chair", "bucket"] -- the initial world 
    loop world0 
+0

但是,我其實增加的項目。那麼,就像刪除項目世界一樣,我可以插入項目世界嗎?另外,如何從我的例子調用函數i_am_at? – 2014-11-09 02:07:27

+0

我增加了一些代碼。要將一個項目追加到列表的前面,可以使用'++'運算符:'[1] ++ [2]'產生'[1,2]'。 – ErikR 2014-11-09 02:56:23

+0

你的'I_am_at'函數只是一個'String'值,而不是IO動作。您可以使用'putStrLn i_am_at'來輸出'i_am_at'返回的值。 – ErikR 2014-11-09 02:59:23