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?

有帮助吗?

解决方案

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".

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top