haskellfunctional-programmingmonadsrecordpointfree

Elegant way to access the value of a record in haskell which is inside a monad


Generalisation of question (read below for specifics to my current problem)

Given a function type definition: f :: MonadIO m -> a -> m B where B is a custom datatype B = B {x y z ...} how can I access a member such as x from the value returned by f?

Problem

I am trying to use the wave package to make an application, but I have a simple problem: I wish to access waveFileFormat of the data type Wave

However simply doing waveFileFormat $ readWaveFile "file" does not work because readWaveFile "file" is actually a MonadIO m => m Wave returned by readWaveFile.

What I have tried and does not work

readWaveFile "file" >>= waveFileFormat readWaveFile "file" >> waveFileFormat

What works (but looks inelegant and horribly long for what it is)

do{wave<-readWaveFile "file"; return $ waveFileFormat wave}


This approach however will not work outside a `do` block because of the assignment . It is also extremely long and like boilerplate. How can I avoid this?

Solution

  • You can use fmap (or its infix operator form, (<$>)):

    waveFileFormat <$> readWaveFile "file"
    

    This has type MonadIO m => m WaveFormat. You can't ever escape the monad, but you can keep manipulating its value to your heart's content.