Question

I'm interoping with a C function that I pass a (callback) function to and it calls it every-time with a different parameter.

I imported it into Haskell and now I have something like this (I've simplified it, of course):

countToFive :: (Int -> IO ()) -> IO ()
countToFive fn = do fn 1; fn 2; fn 3; fn 4; fn 5

I want to make a list of every number passed to fn; something with this signature:

counting :: IO [Int]

That in the example above will (perform the IO, of course) with the result of [1,2,3,4,5].

The imperative approach of counting would be to create a mutable list, and call countToFive with a function that inserts the parameter into the mutable list on every-call, and then just return the list.

What's the functional way to go about it?

Était-ce utile?

La solution

You do it the exact same way—once you're living so deeply in the IO monad many things will feel a great deal like its imperative cousin.

import Data.IORef

counting :: ((Int -> IO ()) -> IO ()) -> IO [Int]
counting fun = do
  store <- newIORef []
  fun (\new -> modifyIORef store (new:))
  readIORef store

Note the use of rather higher order function types to parameterize counting over functions of the type of countToFive. For an even more mind-bending experience it's interesting to note that this method is consistent with "continuation passing style". In a very real sense countToFive "contains" a list of integers and simply has a tricky method of "getting it out".

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top