Композиция функции с монадой 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)