[Haskell-cafe] Is it usual to read a Maybe (IORef a) ?
lennart at augustsson.net
Thu Sep 4 04:44:49 EDT 2008
I would represent the data structure in a pure way, and restrict the
IO monad to the operations that actually do IO.
If you need some kind of mutable graph, I suggest representing that
graph as a map (Data.Map) from node names to neighbors.
The "mutation" is then just updating the map. An extra benefit from
this is that you get really simple undo in your editor.
On Thu, Sep 4, 2008 at 8:53 AM, minh thu <noteed at gmail.com> wrote:
> 2008/9/4 Timothy Goddard <tim at goddard.net.nz>:
>> It looks like this code isn't really in fitting with normal Haskell idioms.
> I guess you mean by Haskell idiom : "pure". But Haskell allows you to
> do IO, etc.
>> 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.
> Thanks for the exemple, but I'm aware of monads (even if I can't still
> use them easily when
> many of them are mixed).
> Here my problem is more about interactively editable data structure
> (at least from the
> point of view of the user). I would be very happy to do it with pure functions.
>> 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.
> I'm looking at the FGL package, it seems very intersting. I don't
> think immutable data
> structures imply poor perfromance, but I think designing the examples you give
> is quite complicated and done by really experienced Haskell programmers.
> Please, don't answer to my problem (even if I haven't really explain
> it) by exposing
> state-of-the-art Haskell goodness.
>> 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.
> Overall, I agree I have to look for a more pure approach. Although, I
> think something like
> FGL required a lot of work. But raising, say, uvector, in face of my
> use of IORef seems a bit
>> Good luck,
> Thank you,
>> On Wed, 03 Sep 2008 22:09:38 minh thu wrote:
>>> 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 ?
>>> Haskell-Cafe mailing list
>>> Haskell-Cafe at haskell.org
>> Haskell-Cafe mailing list
>> Haskell-Cafe at haskell.org
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
More information about the Haskell-Cafe