Mutable List builder in the ST Monad
at master 70 lines 1.5 kB view raw
1-- | Traversing IO lists. 2-- 3-- Code from this module is derived from [Twan van Laarhoven](https://www.twanvl.nl/blog/haskell/unsafe-sequence). 4-- 5-- These operations are tail recursive, while building lists by appending 6-- to its tail mutably. 7module Data.Traversable.IO ( 8 sequenceIO 9 , traverseIO 10 , unfoldIO 11) where 12 13import Data.ListBuilder.Unsafe 14 15import Prelude hiding (length) 16 17 18-- | Traverse implemented in terms of unsafeSetField. 19-- 20-- This operation is tail recursive. 21traverseIO :: (a -> IO b) -> [a] -> IO [b] 22traverseIO _ [] = 23 return [] 24traverseIO f (mx0:xs0) = do 25 x0 <- f mx0 26 let front = [x0] 27 go front xs0 28 return front 29 where 30 go _ [] = return () 31 go back (mx:xs) = do 32 x <- f mx 33 let back' = [x] 34 unsafeSetField 1 back back' 35 go back' xs 36{-# INLINEABLE traverseIO #-} 37 38 39-- | Sequence implemented in terms of unsafeSetField 40-- 41-- This operation is tail recursive. 42sequenceIO :: [IO a] -> IO [a] 43sequenceIO = 44 traverseIO id 45{-# INLINE sequenceIO #-} 46 47 48-- | Unfold a list from an IO action returning a 'Maybe' value. 49-- As long as the function returns `Just`, its value will 50-- be appended to the list. 51unfoldIO :: IO (Maybe a) -> IO [a] 52unfoldIO p = do 53 x <- p 54 case x of 55 Nothing -> 56 return [] 57 Just a -> do 58 let front = [a] 59 go front 60 return front 61 where 62 go back = do 63 x <- p 64 case x of 65 Nothing -> return () 66 Just a -> do 67 let back' = [a] 68 unsafeSetField 1 back back' 69 go back' 70{-# INLINEABLE unfoldIO #-}