Композиция функции с монадой Writer?

Я изучаю Writer монада и иметь следующее:

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 

Ошибка:

"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"

Почему эта ошибка вычисления с . и не $? Возможно, мое понимание состава функций неверно?

2 ответа

Решение

Композиция функций с . означает, что полученная композиция получит аргумент.

Эта часть:

execWriter . myFunction 1 2

Можно написать более явно так:

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

поскольку myFunction принимает только два аргумента, вы получаете ошибку компиляции.

Если бы вы использовали $ в вашем коде, вот так:

execWriter $ myFunction 1 2

Полученный расширенный код эквивалентен этому:

execWriter (myFunction 1 2)

Который действителен.

В дополнение к тому, что сказал Чад, это происходит потому, что обычное приложение функции (без использования $) имеет более высокий приоритет, чем все операторы (инфиксные функции), включая .,

Ваш пример сработал бы, если бы вы написали это так:

(execWriter . myFunction 1) 2

Что эквивалентно:

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

Который затем оценивает:

execWriter (myFunction 1 2)
Другие вопросы по тегам