1

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?
Naitik Mundra
  • 418
  • 3
  • 14
  • 2
    `readWaveFile "file" >>= waveFileFormat` should have been `readWaveFile "file" >>= return . waveFileFormat`, which is identical to `do{wave<-readWaveFile "file"; return $ waveFileFormat wave}`. – Micha Wiedenmann Jul 28 '22 at 20:53
  • @MichaWiedenmann Thank you for pointing that out! I will keep that in mind in the future. – Naitik Mundra Jul 29 '22 at 06:49

1 Answers1

6

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.

luqui
  • 59,485
  • 12
  • 145
  • 204
  • 4
    "*You can't ever escape the monad*" - that depends on the monad. Sure, a `MonadIO` monad makes this hard because you can't escape the `IO` monad (without `unsafePerformIO`), but for other monad types it's usually possible. (Not sure how general the OP's question is meant to be) – Bergi Jul 28 '22 at 21:30
  • Just to clarify, since I am new to the concept of monads, can all monads be considered functors? (For eg, here you use `fmap` which is for functors but for a monad.) – Naitik Mundra Jul 29 '22 at 06:48
  • Never mind, found https://stackoverflow.com/questions/45252709/what-is-the-difference-between-a-functor-and-a-monad, that answers it. – Naitik Mundra Jul 29 '22 at 06:56
  • 4
    @NaitikMundra, all monads are also functors. Also the answers on that page are ... um ... wrong. – luqui Jul 29 '22 at 19:04
  • @luqui could you please elaborate? – Naitik Mundra Jul 29 '22 at 19:29
  • I found this: https://wiki.haskell.org/Monad/, which says "the Applicative typeclass is a superclass of Monad, and the Functor typeclass is a superclass of Applicative. This means that all monads are applicatives, all applicatives are functors, and therefore all monads are also functors." The haskell wiki is a relaible source, right? So can I trust the info here? – Naitik Mundra Jul 29 '22 at 19:30
  • 2
    @Bergi you can't ever escape a monad _polymorphically_. – is7s Jul 30 '22 at 00:07
  • @is7s Sure, I was referring to specific monads. – Bergi Jul 30 '22 at 00:18
  • @NaitikMundra yeah that's correct, and haskellwiki should be generally trustworthy :) – luqui Jul 30 '22 at 08:34