[Haskell-cafe] Is it usual to read a Maybe (IORef a) ?
Timothy Goddard
tim at goddard.net.nz
Thu Sep 4 02:33:22 EDT 2008
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 at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
More information about the Haskell-Cafe
mailing list