[Haskell-cafe] Is it usual to read a Maybe (IORef a) ?
noteed at gmail.com
Thu Sep 4 05:03:53 EDT 2008
2008/9/4 Lennart Augustsson <lennart at augustsson.net>:
> 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.
This is what I was looking yesterday and right now,probably using Data.IntMap.
Data.FiniteMap on hackage says it's deprecated. Do you know in favor of what ?
FGL uses its own Data.Graph.Inductive.Internal.FiniteMap, saying
not enough. Should it use Data.Map ?
Thanks for the suggestion,
> -- Lennart
> 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