Function composition with the Writer monad?

141 Views Asked by At

I'm studying the Writer monad and have the following:

myFunction :: Int -> Int -> Writer String Int
myFunction e1 e2 
   | e1 > e2 = do
      tell ("E1 greater")
      return (e1)
   | otherwise = do
      tell ("E2 greater")
      return (e2)

main = do
-- execWriter :: Writer w a -> w 
   print $ execWriter . myFunction 1 2 

Error:

"Couldn't match type ‘WriterT String Data.Functor.Identity.Identity Int’with ‘a0 -> Writer c0 a1’
  Expected type: a0 -> Writer c0 a1
    Actual type: Writer String Int"

Why does this computation error with . and not $? Perhaps my understanding of function composition is incorrect?

2

There are 2 best solutions below

0
On BEST ANSWER

Function composition with . means that the resulting composition will receive an argument.

This portion:

execWriter . myFunction 1 2

Can be written more explicitly like this:

(\x -> execWriter (myFunction 1 2 x))

Since myFunction only takes two arguments, you are getting a compile error.

Had you used $ in your code, like this:

execWriter $ myFunction 1 2

The resulting code expanded is equivalent to this:

execWriter (myFunction 1 2)

Which is valid.

0
On

In addition to what Chad said, this happens because regular function application (without using $) has a higher priority than all operators (infix functions), including ..

Your example would have worked if you had written it like this:

(execWriter . myFunction 1) 2

Which is equivalent to:

(\x -> execWriter (myFunction 1 x)) 2

Which then evaluates to:

execWriter (myFunction 1 2)