Data.Vector的Monadic concatMap?

时间:2017-02-14 19:50:46

标签: haskell vector monads

我正在寻找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函数实际上并不依赖于获取值的元组,但示例所基于的实际代码确实存在。

1 个答案:

答案 0 :(得分:5)

Monad m => (a -> m (Vector b)) -> Vector a -> m (Vector b)并不太难 - 我们可以依赖Functor的{​​{1}},MonadTraversable个实例。需要注意的是,您需要使用常规(未拆箱)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类实例)。