Reputation: 2011
I am learning about monads in the book 'Learn You a Haskell for Great Good!' by Miran Lipovaca. I am reading about how the Control.Monad.Writer module exports the Writer w a
type along with its Monad instance and some useful functions for dealing with values of this type.
For the following code:
newtype Writer w a = Writer { runWriter :: (a,w) }
I know that the a
type parameter represents the type of some value, and the w
type parameter represents the type of the attached monoid value. Am I correct in saying that by passing w
and a
to the Writer
type constructor, you get a Writer monad in return, with this monad only having one function which is the runWriter
function?
In the book it says that the runWriter
function takes a tuple that's wrapped in a Writer
newtype and unwraps it, returning a simple tuple. However the type declaration of runWriter
is runWriter :: (a,w)
, it doesn't take any parameters as input. How does runWriter
take a tuple that's wrapped in a newtype and return just a simple tuple?
Upvotes: 2
Views: 437
Reputation: 116139
Am I correct in saying that by passing
w
anda
to the Writer type constructor, you get a Writer monad in return,
No, Writer w
is the monad (assuming Monoid w
). Writer w a
is a type.
with this monad only having one function which is the
runWriter
function?
No, the type Writer w a
is, essentially, a pair type (a,w)
. There are no functions inside.
You can pretend that the type is defined in the following way
newtype Writer w a = Writer (a,w)
and that there is a separate convenience "unwrapping" function
runWriter :: Writer w a -> (a,w)
runWriter (Writer p) = p
You can think of these functions as being mutual inverses:
Writer :: (a,w) -> Writer w a -- "wrapper"
runWriter :: Writer w a -> (a,w) -- "unwrapper"
Using the record syntax in data
declarations indeed defines functions taking an implicit argument (in addition to the data type itself).
Any type
data T = MkT { f :: Int, g :: String }
defines the data type T
, data constructor MkT
, and functions f
, g
having an implicit T
argument,
f :: T -> Int -- f (MkT i _) = i
g :: T -> String -- g (MkT _ s) = s
Record syntax with newtype
s works in the same way, except that there must be exactly one field (named runWriter
, in your example).
Upvotes: 5