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_Types_Coroutine - Fatal编程技术网

Haskell 广义共程悬挂式

Haskell 广义共程悬挂式,haskell,types,coroutine,Haskell,Types,Coroutine,我正在尝试,并且有一个协同程序,它将从外部请求所有IO操作。因此,我有自己的定制悬架类型IORequest。问题是,对于每种返回类型,我都需要向IORequest添加一个额外的构造函数 下面是一个工作示例(需要和) (不过,我无法使它工作,因为当我们尝试在str中运行它时,a会逃逸。您关于将数据类型更改为包含存在量词的评论似乎完全合理。您的大多数函数不会更改 data IORequest x = forall a . RunIO (IO a) (a -> x) instance Func

我正在尝试,并且有一个协同程序,它将从外部请求所有
IO
操作。因此,我有自己的定制悬架类型
IORequest
。问题是,对于每种返回类型,我都需要向
IORequest
添加一个额外的构造函数

下面是一个工作示例(需要和)


(不过,我无法使它工作,因为当我们尝试在
str中运行它时,
a
会逃逸。您关于将数据类型更改为包含存在量词的评论似乎完全合理。您的大多数函数不会更改

data IORequest x = forall a . RunIO (IO a) (a -> x)

instance Functor IORequest where 
  fmap f (RunIO x g) = RunIO x (f.g) 
将其他构造函数替换为
RunIO

request :: Monad m => IO () -> Coroutine IORequest m ()
request x = suspend (RunIO x return)

requestString :: Monad m => IO String -> Coroutine IORequest m String
requestString x = suspend (RunIO x return)
loop :: Coroutine IORequest (State Int) Int -> Int -> IO ()
loop routine state =
  do let (request, state') = runState (resume routine) state
     case request of
       Left (RunIO cmd q') -> do
         a <- cmd
         loop (q' a) state'
       Right result -> do
         print result
您的循环函数也不会真正改变-您只需要不忽略
RunIO
中的值:

request :: Monad m => IO () -> Coroutine IORequest m ()
request x = suspend (RunIO x return)

requestString :: Monad m => IO String -> Coroutine IORequest m String
requestString x = suspend (RunIO x return)
loop :: Coroutine IORequest (State Int) Int -> Int -> IO ()
loop routine state =
  do let (request, state') = runState (resume routine) state
     case request of
       Left (RunIO cmd q') -> do
         a <- cmd
         loop (q' a) state'
       Right result -> do
         print result
然后可以清楚地看到,
IORequest
现在只是与
IO
同构。这遵循左kan扩展定律(即,
lantocomposedjaint
composedjainttolan
是同构的见证),但可以直接写入:

actuallyJustIO_1 :: IORequest a -> IO a 
actuallyJustIO_1 = fmap runIdentity . lanToComposedAdjoint 

actuallyJustIO_2 :: IO a -> IORequest a 
actuallyJustIO_2 = composedAdjointToLan . fmap Identity 

这两个函数显然是彼此的左逆和右逆,见证了
IORequest
IO

之间的同构。是否真的有必要将IO放入函子中,而不是将其作为
Coroutine f m
的“基单子”?直观地说,这就是它所属的位置。如果我删除IO的外观在
IORequest
中,我可以写入
requestString m=lift m>=\x->suspend(GetString x return)
使用基本相同的类型,
requestString::Monad m=>m String->Coroutine IORequest m String
我对存在类型没有问题。当然,它相当于
newtype IORequest x=IORequest{runIORequest::iox}
,不是吗?这只是一个实验。我想把纯代码从IO中分离出来。假设这个协同程序非常庞大,它需要时不时地进行一些IO调用。我不知道它是否会有任何好处,ghc是否能够以当前的形式对这个协同程序进行更好的优化,或者完全在IO中运行的代码会做得更好?我有n好的,我不是反对它,只是提出一些观点。我认为,如果你使用这种类型的东西,最好是在底部使用IO,而不是标识;可以说,你已经为复杂性付出了代价。Coroutine确实有一个MonadIO的例子。但是暂停会有所改变我认为像
ReadFile FilePath(Text->x)
这样的程序更符合这个库的精神。
actuallyJustIO_1 :: IORequest a -> IO a 
actuallyJustIO_1 = fmap runIdentity . lanToComposedAdjoint 

actuallyJustIO_2 :: IO a -> IORequest a 
actuallyJustIO_2 = composedAdjointToLan . fmap Identity