Функция составная подсказка

Просто ищу объяснение, как работает следующая композиция:

(=<<) . return

где

(=<<) ::       (a -> m b) -> m a -> m b
return :: a -> m a
(.) :: (b -> c) -> (a -> b) -> a -> c

Окончательный тип:

GHCi> :t (=<<) . return
(=<<) . return :: Monad m => m b -> m a -> m b

Я не могу понять, как можно сопоставить ма с (а -> мб), т.е. как применить результат return, который является простым типом, к первому аргументу (=<<), ожидающему тип функции?

2 ответа

Решение

Объяснение:

  1. Ваш return (возможно, неожиданно) другой монады, чем ваша =<<,
  2. Монада, которую он использует, является монадой читателя (->) r,

Компилятор пытается унифицировать результат return :: c -> m' c с первым аргументом (a -> m b) -> m a -> m bтак что унифицировать m' c с a -> m b, Единственная возможность состоит в том, что m' читатель монада (->) r для некоторых r, Далее он пытается объединить (->) r c с (преобразуется в префиксную нотацию) (->) a (m b), который решается установкой r в a а также c в m b, Таким образом, после объединения, компилятор получает наиболее общий тип

return :: (m b) -> ((->) a (m b))

или в обычной записи инфикса

return :: (m b) -> (a -> m b)

Смотрите также:


Редактировать: чтобы определить монаду, нам нужен (частично примененный) тип вида * -> *, Это почти всегда частично применяемые конструкторы данных, но в данном конкретном случае мы рассматриваем -> как оператор типа, который принимает 2 аргумента типа и создает новый тип (тип функции). Так для любого данного типа rчастично примененное выражение (->) r это тип вида * -> *, Как оказалось, существует простой способ описать операции монады над ним. См. Монаду Control.Reader, а также эту статью, которая объясняет это. Операции с монадой для Reader реализованы точно так же, как для (->)Единственное отличие состоит в том, что Reader оборачивает операции в отдельный тип данных.

Я снова, с писанинами, кладу вещи рядом, чтобы помочь в визуальном понимании:

g = ((=<<) . return)   {-

((=<<) . return) x y 
         ===   (=<<)    (return x)    y               return :: a' -> m' a'
               (=<<) :: (a -> m b) -> m a -> m b      return x :: m' a' , x :: a'
                          m'  a'                      m' ~ ((->) a) , a' ~ m b 

return x === const x             -- instance Monad ((->) a) where return = const
g x y === y >>= (\_ -> x) === y >> x   (!!)
-}

g :: m b -> m a -> m b

Так что, как оказалось (и это было очевидно из сигнатуры типа), g === flip (>>):

Prelude> ((=<<).return) [1] "xyz"   -- ===  (=<<) (const [1]) "xyz" 
                                    -- ===  "xyz" >>= const [1]
                                    -- ===  "xyz" >> [1]
                                    -- ===  (>> [1]) "xyz"
[1,1,1]
Другие вопросы по тегам