Пример, который вы приводите, работает. Давайте объясним, почему:
three f = f . f . f
-- so...
three :: (a -> a) -> a -> a
Функция должна иметь тип a -> a
, потому что она получит собственный аргумент, для которого требуется тип. (2+)
имеет тип Num a => a -> a
, поэтому three (2+) 4
будет отлично работать.
Однако, когда вы передаете функцию типа return
типа Monad m => a -> m a
, которая возвращает другой тип, она не будет соответствовать установленному нами требованию (a -> a)
. Это где и когда ваша функция не будет работать.
Пока вы занимаетесь этим, попробуйте создать такую функцию, как doTimes
с типом Integer -> (a -> a) -> a -> a
, которая выполняет данную функцию заданное число раз - это хороший следующий шаг после выполнения этой функции.