2011-06-08 55 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"