本文介绍了为什么嵌套在其他monad中的IO不能执行?有没有办法强制他们?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我最后一个问题的后续。


解决这个问题的方法是删除一些monad,并允许执行IO操作。



为什么我需要让单子们安静?有没有一种方法来执行IO而不拆开?



注意:这是一个 what-if 多于这是一个关于好的或不好的做法的问题。 可能这会帮助你想到 IO as type IO a = World - > (a,世界);也就是一个函数,它将当前计算机的状态作为其唯一参数,并返回一个新的状态以及一些值 a 。这与GHC内部的 IO 的实际执行没有太大的区别,所以希望我们可以原谅这种类比的交流方式。



所以 readFile :: FilePath - > IO字符串,例如,变为 readFile :: FilePath - >世界 - > (a,World)



main :: IO() main :: World - > ((),World)



然而,这意味着类型为 IO _ 是惰性的。他们只是功能!函数在赋值之前不能做任何事情;在我们的例子中,函数需要的值是 World 对象,我们无法构建。这就是Haskell中IO的美妙之处:我们可以通过使用我们所熟悉并喜爱的monadic运算符(return,bind)来建立一个 IO 动作,但它只能在运行时传入 World 对象。



这意味着任何 IO 我们构建的行为不会穿过 main 不会被执行。



foobar :: [Char] - > IO [IO()] ,我们当然可以观察到返回值:

  main :: IO ()
main = do
ios< - foobarstring
printgoodbye

但是,直到我们解构 ios 并绑定内部的 IO 这些操作值收到他们希望获得的 World

$ p $ main :: IO()
main = do
ios< - foobar
ios !! 0
ios !! 1
ios !! 2
...
printgoodbye

或者,

  main = do 
ios< - foobar
序列ios
printgoodbye

希望这有助于您。


This is a follow up of my last question.IO action nested in other monads not executing

The solution to that question was to remove some of the monads, and that allowed the IO action to execute.

Why did I need to unnest the monads? Is there a way to execute the IO without unnesting?

Note: This is a what-if more than it is a question about good or bad practice.

解决方案

Perhaps it would help to think of IO as type IO a = World -> (a, World); that is, a function that takes as its only parameter the current state of your computer and returns a new state along with some value a. This is not too dissimilar from the actual implementation of IO in GHC internals, so hopefully we can forgive the (abject) method of communicating by analogy here.

So readFile :: FilePath -> IO String, for example, becomes readFile :: FilePath -> World -> (a, World).

And main :: IO () is really main :: World -> ((), World).

What this means, however, is that values with type IO _ are inert. They are just functions! Functions cannot do anything until they are given a value; in our case, the value the function wants is a World object, which we have no way of constructing. Therein lies the beauty of IO in Haskell: we can build up an IO action by using the monadic operators we know and love (return, bind) but it cannot do anything until the runtime passes in the World object.

Which means that any IO action we build that isn't threaded through main won't be executed.

So, with foobar :: [Char] -> IO [IO ()], we can certainly observe the return value:

main :: IO ()
main = do
  ios <- foobar "string"
  print "goodbye"

But it's not until we deconstruct ios and bind the internal IO values that those actions receive the World they desire:

main :: IO ()
main = do
  ios <- foobar
  ios !! 0
  ios !! 1
  ios !! 2
  ...
  print "goodbye"

Or, for short,

main = do
  ios <- foobar
  sequence ios
  print "goodbye"

Hope this helps.

这篇关于为什么嵌套在其他monad中的IO不能执行?有没有办法强制他们?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 02:33