
It looks like this code isn't really in fitting with normal Haskell idioms. Emulating C in Haskell will only give you a harder way of writing C. Don't think about emulating a potentially null pointer with Maybe (IORef a) and passing this to a function to read content unless you also want to implement the function "segfault :: IO ()". You really need to ask yourself whether it makes sense to read a NULL / Nothing field. In C this would cause a segfault. The idea in Haskell is that you don't allow invalid values to be passed in to a function at all. Each function should be pure and accept only sensible inputs, allowing you to analyse what each function does in isolation from the rest of the program. In Haskell, functions should use the type system to only accept arguments which make sense. The caller should handle the possibility that a function it calls returns nothing, not expect every other callee to do so. The Maybe monad helps with this for many cases: lookupEmployee :: Integer -> Maybe Employee lookupPassportNo :: Employee -> PassportNo lookupMarriageCertificate :: PassportNo -> Maybe MarriageCert getPassportNumbers :: MarriageCert -> (PassportNo, PassportNo) getNameFromPassport :: PassportNo -> Maybe String lookupSpouse :: Integer -> Maybe String lookupSpouse employee_no = do employee <- lookupEmployee employee_no let passport = lookupPassportNo employee cert <- lookupMarriageCertificate let (p1, p2) = getPassportNumbers cert let partner = if p1 == passport then p2 else p1 getNameFromPassport partner In this example, if any lookup which can fail does, the result is Nothing. Each lookup function can assume that a valid argument is present, though some types of lookup may still give no result. The caller chooses how to account for this inability to find a match, in this case by itself having no result. The thing I'm more concerned about here is the use of IORefs inside data structures at all. A data structure containing IORefs is mutable and can only be manipulated in the IO monad, which defeats the point of Haskell. There is a use case for using mutable structures for some resource-intensive operations, but even then it's often trading short-term speed for long term difficulties. If you think immutable structures imply poor performance, take a look at projects such as uvector and Data Parallel Haskell - immutable data structures which beat the hell out traditional, C-like techniques. If you must use IORefs, consider only using them to hold the whole structure, which is modified by normal, pure functions. If you don't think you can make do with this, you're probably still thinking about the program in an imperative manner. You will probably be better off either rethinking how you're doing things or, if you cannot translate the concepts to a functional form, using an imperative language. Good luck, Tim On Wed, 03 Sep 2008 22:09:38 minh thu wrote:
Hi,
I'd like to write a data structure to be used inside the IO monad. The structure has some handles of type Maybe (IORef a), i.e. IORef are pointers and the Maybe is like null pointers.
So I came up with the following functions :
readHandle :: Maybe (IORef a) -> IO (Maybe a) readField :: (a -> b) -> Maybe (IORef a) -> IO (Maybe b)
readHandle Nothing = do return Nothing readHandle (Just r) = do v <- readIORef r return $ Just v
readField f h = do m <- readHandle h return $ fmap f m
Is it something usual ? Are there any related functions in the standard libraries ?
Thanks, Thu _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe