vectorパッケージのData.Vector
にはgenerateという関数がある。
generate :: Int -> (Int -> a) -> Vector a
型から全てを知ることはできないが、だいたい想像通りgenerate n f
は[f 0, f 1, f 2, ...f (n - 1)]
からなるVector
を生成する。しかし、これは要素を評価はしない。生成されるのはあくまでサンクのVectorだ。
Prelude > import Data.Vector as V Prelude V> V.length $ V.generate 5 (const undefined) 5
vector
は速くて正格そうなイメージがあるが、ボックス化される方に関して、基本的に正格性は最小限なので注意しよう。どう工夫してもgenerate
だけで正格なVectorは作れないので、generateM
を使おう。
Prelude V> V.length $ runIdentity $ V.generateM 5 $ const $ pure $! undefined 5
Identityではダメなようだ…だが、継続モナドCont
を使うとうまくいく。
cont :: ((a -> r) -> r) -> Cont r a runCont :: Cont r a -> (a -> r) -> r
V.length $ flip runCont id $ V.generateM 5 $ \_ -> cont $ \k -> k $! undefined *** Exception: Prelude.undefined
継続最高。