Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 哈斯克尔_Haskell_Monads_If Statement_Do Notation - Fatal编程技术网

Haskell 哈斯克尔

Haskell 哈斯克尔,haskell,monads,if-statement,do-notation,Haskell,Monads,If Statement,Do Notation,使用do-符号: Type error in application *** Expression : putStr "0" putStr "0" *** Term : putStr *** Type : String -> IO () *** Does not match : a -> b -> c -> d do 对此的经典解释是,你想从两个现有的一元值中形成一个新的一元值。让我们看看putStr的类型 do a

使用
do
-符号:

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

对此的经典解释是,你想从两个现有的一元值中形成一个新的一元值。让我们看看putStr的类型

do
  a <- something
  if a 
  then
    do
      cmd1
      cmd2
  else
    do
      cmd3
      cmd4
  cmd5 -- this comes after the 'then' and the 'else'
这意味着它是一个黑匣子,当执行时,它将“返回”单元类型的(唯一)值。一元计算背后的关键思想是,您有一个组合器
>=
,它将两个一元表达式组合在一起,将一个表达式的结果输入下一个表达式(更准确地说,是一个创建下一个表达式的函数)。一个关键点是
IO
库提供了这个组合器,这意味着

  • 它[IO在本例中]可以跳过第二个一元值,例如当第一个一元值引发异常时
  • 如果
    IO
    a
    RealWorld
    状态包含打开的文件句柄等,它可以传递其他数据
  • 它可以“确保”第一个先求值,这与大多数lambda表达式求值不同,在lambda表达式求值中,最外层(“last”)项首先展开。这一点对于打印非常重要,因为第一次打印需要首先改变世界
在你的情况下,像这样使用它

IO ()
当然,有一条捷径

putStr "0" >>= (\c -> putStr "0")
还有do符号,正如另一张海报所提到的,它更像是一种语法糖

putStr "0" >> putStr "0"

对于这个人为的例子,您也可以使用如下案例:

do
    putStr "0"
    putStr "0"
使用do语法可能更容易阅读,但我想先在不使用do语法的情况下展示它,只是为了强调do语法只是语法,实际上并没有做任何特殊的事情。这里是do语法

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"
main=do
输入putStrLn“0”
1->putStrLn“0”
2->执行putStr“0”
putStrLn“0”
3->执行putStr“0”
putStr“0”
putStrLn“0”
_->putStrLn“无限”

我更喜欢将
do
else
放在同一行,然后
@fuzzxl对,我也是。但我想强调的是,这不是什么神奇的
,然后再做
语法。这只是
if-then-else
表达式分支中的正常
do
-符号。我只是在开始上课时使用了
do
。。这种方法解决了一些关于术语的小问题:单词“monad”用作没有其他限定词的名词,通常只指具有
monad
实例的类型构造函数。某些类型的
ma
值,其中
m
是单子,通常称为其他值。@camcann,关于术语:我见过“命令”和“动作”。在“
putstrs
中,是一个打印字符串s的
IO
操作。@Lambdageek:这对
IO
和其他一些操作很好,但应用于列表之类的东西听起来很傻。“一元价值”之类的变体似乎在一般情况下使用,但这很笨拙。我更喜欢“一元价值”而不是“行动”。当我们达成一致意见时,我会编辑条目。@gatoatigrado:唉,如果通用术语中有一个好的通用术语,我一开始就会这么说。我建议你要么用“动作”来表示IO,要么用“一元值”或“一元中的值”来表示。但仅仅是“单子”就容易造成混乱。我确实记得有人建议“mote”,这很可爱,但我不认为它流行起来。:)这并不能回答您的问题,但我希望您认识到,将其作为模式匹配编写会更好<代码>0->…1->…
@Chuck IO的案例输入与模式匹配是否可能,因为它是一个IO程序
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"
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"