Haskell 扩展只接受两个输入到多个输入的asyncs race函数?

Haskell 扩展只接受两个输入到多个输入的asyncs race函数?,haskell,asynchronous,Haskell,Asynchronous,我试图扩展asyncsrace函数,这样它就可以应用于列表中的每个IO函数,但是我在推理扩展时遇到了麻烦 我的第一种方法是将列表一分为二,并将其压缩在一起,这样每个条目都是一对不同的组合。完成后,在列表中映射race,并返回一个随机条目作为事实上最快的条目。这种方法的问题是,我遇到了以下错误,无法找到解决方案来缓解: No instance for (Show (IO Int)) arising from a use of ‘print’ 经过几个小时的尝试,我找到了一个解决方案,然后看看函数

我试图扩展asyncs
race
函数,这样它就可以应用于列表中的每个IO函数,但是我在推理扩展时遇到了麻烦

我的第一种方法是将列表一分为二,并将其压缩在一起,这样每个条目都是一对不同的组合。完成后,在列表中映射race,并返回一个随机条目作为事实上最快的条目。这种方法的问题是,我遇到了以下错误,无法找到解决方案来缓解:

No instance for (Show (IO Int)) arising from a use of ‘print’
经过几个小时的尝试,我找到了一个解决方案,然后看看函数本身是如何工作的。我意识到它的工作原理很像
max
操作符,因为它必须嵌套

race a1 (race a2 a3)
= {Apply race, race a2 a3 := alpha}
race a1 alpha
= {Apply race}
alpha'
我认为这可能是一个更好的方法,但我不确定的是种族行为本身。如果我在这个例子中应用了内环,那么它返回的是对内环比较的求值,而不是函数,那么在外环中,实际发生的是对函数和求值函数应用内环


任何指导都将不胜感激

如果你不在乎是哪个动作首先给出了答案,我认为这样的事情应该没问题:

raceAll :: [IO a] -> IO a
raceAll [] = fail "whoops"
raceAll acts = go acts where
    go [io] = io
    go ios = go (raceAdjacent ios)
    raceAdjacent (io:io':ios) = (either id id <$> race io io') : raceAdjacent ios
    raceAdjacent short = short
这会将列表的长度减半,然后
go
只需迭代该过程,直到只剩下一件事,即所有原始操作之间的竞争

如果您确实想知道哪个动作先完成,您可以在比赛之前用索引将动作压缩:

raceAllIndexed :: [IO a] -> IO (Int, a)
raceAllIndexed acts = raceAll (zipWith (\n io -> (,) n <$> io) [0..] acts)
raceAllindex::[IO a]->IO(Int,a)
raceAllIndexed acts=raceAll(zipWith(\n io->(,)n io)[0..]acts)
您可以在ghci中试用:

> raceAllIndexed [threadDelay ((n*(-1000000)) `mod` 3333333) | n <- [1..10]]
(2,())
>raceAllIndexed[threadDelay((n*(-1000000))`mod`3333333)|n“async”在
IO
上提供了一种新类型

同时
有一个实例,其中一个操作与另一个操作竞争

为了定义
raceAll
,我们可以将其与中的函数结合使用:

raceAll :: [IO a] -> IO a
raceAll = runConcurrently . asum . map Concurrently
请注意,此版本的
raceAll
将永远等待空列表,因为这是
同时执行的功能


为了好玩,定义函数的一种更古怪的方法是:

import Data.Foldable
import Data.Monoid (Alt(..))
import Data.Coerce (coerce)
import Control.Concurrent.Async

raceAll :: [IO a] -> IO a 
raceAll xs = 
    let Alt (Concurrently x) = foldMap coerce xs
     in x

非常感谢,但是我在理解第一个街区时遇到了一点困难!我可以沿着你的街区一直走到相邻的线,你能解释一下吗?@JiangShi我添加了一些文字;这有帮助吗?这是一个完美的解释!谢谢!
import Data.Foldable
import Data.Monoid (Alt(..))
import Data.Coerce (coerce)
import Control.Concurrent.Async

raceAll :: [IO a] -> IO a 
raceAll xs = 
    let Alt (Concurrently x) = foldMap coerce xs
     in x