我正在寻找Data.Vector包中的某些内容,它的工作方式与concatMap
类似,但适用于monad。 concatMap
有类型...
(a -> Vector b) -> Vector a -> Vector b
但我正在寻找类型为......
的东西(Monad m) => (a -> m (Vector b)) -> Vector a -> m (Vector b)
...或者,特别是以下任何一个:
(MonadRandom m) => ((Int, Int) -> m (Vector Int))
-> Vector (Int, Int) -> m (Vector Int)
(MonadRandom m) => (Int -> Int -> m (Vector Int))
-> Vector (Int, Int) -> m (Vector Int)
下面的代码应该让我知道我尝试做什么但会产生错误
无法将
VU.Vector Int
类型与Int
匹配 预期类型:m (VU.Vector Int)
实际类型:m (VU.Vector (VU.Vector Int))
在表达式中:return $ VU.concatMap mate mates
import Control.Monad
import Control.Monad.Random
import qualified Data.Vector.Unboxed as VU
testReprod :: IO()
testReprod = do
let parents = VU.fromList [1::Int,2,3,4,5,6,7,8,9,10]
children <- reproduce parents
print children
-- concat monadic
reproduce :: (MonadRandom m) => (VU.Vector Int) -> m (VU.Vector Int)
reproduce parents = return $ VU.concatMap mate mates
where
half = VU.length parents `div` 2
mates = VU.zip (VU.take half parents) (VU.drop half parents)
mate :: (MonadRandom m) => (Int, Int) -> m (VU.Vector Int)
mate (a, b) = do
r1 <- getRandomR(0,5)
r2 <- getRandomR(0,5)
return $ VU.fromList [a+r1, b+r2]
虽然示例中的mate
函数实际上并不依赖于获取值的元组,但示例所基于的实际代码确实存在。
答案 0 :(得分:5)
Monad m => (a -> m (Vector b)) -> Vector a -> m (Vector b)
并不太难 - 我们可以依赖Functor
的{{1}},Monad
和Traversable
个实例。需要注意的是,您需要使用常规(未拆箱)Vector
。
Vector
对于未装箱的向量执行此操作的问题是,在中间import Data.Vector (Vector)
import Control.Monad (join)
concatMapM :: Monad m => (a -> m (Vector b)) -> Vector a -> m (Vector b)
concatMapM f v = join <$> sequence (fmap f v)
步骤中,我有fmap f v
并且没有合理的Vector (m (Vector b))
(也不是必需的对应data instance
类实例)。