5

Haskell wiki has the following question:

https://en.wikibooks.org/wiki/Haskell/Higher-order_functions for :: a -> (a -> Bool) -> (a -> a) -> (a -> IO ()) -> IO () for i p f job = -- ???

I was able to come up with the following implementation:

generate :: a -> (a->Bool) -> (a->a) -> [a]
generate s cnd incr = if (cnd s) then [] else [s] ++ generate (incr s) cnd incr

-- collapse :: [IO ()] -> IO ()
-- collapse (x:xs) = x ++ collapse xs
-- does not work ^^^^^^


for::a->(a->Bool)->(a->a)->(a->IO())->IO()
for s cnd incr ioFn = map (ioFn) (generate s cnd incr)

Ofcourse map (ioFn) (generate s cnd incr) results in [IO ()]. I am not sure how this can be transformed to IO () I need something like foldl but the one that works with [IO ()] instead of [a].

coder_bro
  • 10,503
  • 13
  • 56
  • 88
  • 1
    You canuse [**sequence_**](https://hackage.haskell.org/package/base-4.12.0.0/docs/Prelude.html#v:sequence-95-) – Willem Van Onsem Oct 24 '18 at 12:27
  • 2
    `generate s cnd incr = takeWhile cnd (iterate incr s)` – 4castle Oct 24 '18 at 12:55
  • 4
    `[IO ()]` is a more specific instance of `[a]` (in which `a` is `IO ()`) so you can pass it to `foldl`. Also you can ask hoogle this kind of question: https://hoogle.haskell.org/?hoogle=%5BIO%20()%5D%20-%3E%20IO%20()&scope=set%3Ahaskell-platform – jberryman Oct 24 '18 at 15:25
  • 1
    Apart from `sequence_`, you could write this as a fold directly using e.g. `foldr (*>) (pure ())` (or `foldr (>>) (return ())`). This is more or less what `sequence`/`sequence_`/`sequenceA` do: join up the actions using applicative/monadic sequencing (`*>`/`>>`) with the “base case” being an action that does nothing (`pure ()`/`return ()`). – Jon Purdy Oct 25 '18 at 18:12

1 Answers1

10

The function you are looking for is:

sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()

But we can actually just replace map, such that we do not need an extra function. You can use mapM_ :: Monad m => (a -> m b) -> [a] -> m () here instead of map, so:

for :: a -> (a -> Bool) -> (a -> a) -> (a -> IO ()) -> IO()
for s cnd incr ioFn = mapM_ ioFn (generate s cnd incr)

This thus will apply the function ioFun on all elements of generate s cnd incr, and eventually return the unit ().

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555