2011-06-08 77 views
4
input <- readLn 
if (input == 0) 
then 
    putStr "0" 
else if (input ==1) 
then 
    putStr "1" 
else if (input ==2) 

在這種塞納里奧如何在thenelse if使用多個putStr用?哈斯克爾的if else

當我試圖得到一個錯誤

Type error in application 
*** Expression  : putStr "0" putStr "0" 
*** Term   : putStr 
*** Type   : String -> IO() 
*** Does not match : a -> b -> c -> d 
+3

這並不回答你的問題,但我希望你認識到這將會更好地寫成模式匹配。 'case case input of 0 - > ... 1 - > ...' – Chuck 2011-06-08 19:28:47

+0

@Chuck IO模式匹配是可能的,因爲它是一個IO程序 – Sudantha 2011-06-09 03:24:52

回答

8

使用do -notation:

do 
    a <- something 
    if a 
    then 
    do 
     cmd1 
     cmd2 
    else 
    do 
     cmd3 
     cmd4 
    cmd5 -- this comes after the 'then' and the 'else' 
+0

我更喜歡把'do'與'else'和'then'一起放在同一行上。 – fuz 2011-06-08 19:03:16

+3

@FUZxxl對,我也是。但我想強調,這不是一些神奇的'然後''語法。這只是'if-then-else'表達式的分支內的普通'do'符號。 – Lambdageek 2011-06-08 19:04:53

+0

我只在課程開始時使用'do' ..這個方法解決了問題 – Sudantha 2011-06-09 03:35:38

6

這種情況的典型解釋是,要形成新的一元價值了兩個現。讓我們來看看putStr的類型,

IO() 

這意味着它的一些黑盒子,在執行時,將「迴歸」單位類型的(一個和唯一的)值。單子計算背後的關鍵思想是你有一個組合子>>=,它將把兩個單子表達式放在一起,把一個結果送到下一個(更準確地說,一個創建下一個的函數)。一個關鍵的一點是,IO提供了這種組合子,這意味着,

  • 它[IO在這種情況下]可以跳過第二單子值,例如,當第一個拋出異常。
  • 它可以通過周圍的其他數據,在IO含有打開的文件句柄一個RealWorld狀態的情況下,等
  • 它可以「保證」,即第一個計算第一,不像大多數lambda表達式評估,其中最外面的( 「最後」)條款首先被擴展。這對於印刷很重要,第一張印刷品需要首先改變世界。

在你的情況下,像這樣使用,

putStr "0" >>= (\c -> putStr "0") 

有一個捷徑,當然,

putStr "0" >> putStr "0" 

和DO-符號,如由其他的海報,這是提到還有更多語法糖,

do 
    putStr "0" 
    putStr "0" 
+0

關於術語的小詭計:用作沒有其他限定詞的名詞「monad」通常僅指具有「Monad」實例的類型構造函數。某些類型'm a'的值,其中'm'是一個monad,通常稱爲別的東西。 – 2011-06-08 19:24:55

+0

@camccann,關於術​​語:我見過「命令」和「動作」。正如在「'putStr s'是一個'IO'操作,打印字符串s」。 – Lambdageek 2011-06-08 19:46:34

+0

@Lambdageek:這對'IO'和其他人來說很好,但聽起來很愚蠢的應用於列表。像「一元價值」這樣的變化似乎被用在一般情況下,但這非常笨拙。 – 2011-06-08 19:49:35

4

對於這個人爲的例子,y OU不妨使用的情況下,像這樣:

main = readLn >>= \input -> case input of 
    0 -> putStrLn "0" 

    1 -> putStrLn "0" 

    2 -> putStr "0" 
     >> putStrLn "0" 

    3 -> putStr "0" 
     >> putStr "0" 
     >> putStrLn "0" 

    _ -> putStrLn "infinite" 

這可能是也許是有做語法更具可讀性,但我想說的是,不首先做語法,只是強調,做語法只是語法實際上並沒有做任何特別的事情。這裏是do語法。

main = do 
    input <- readLn 
    case input of 
     0 -> putStrLn "0" 

     1 -> putStrLn "0" 

     2 -> do putStr "0" 
       putStrLn "0" 

     3 -> do putStr "0" 
       putStr "0" 
       putStrLn "0" 

     _ -> putStrLn "infinite"