2015-09-01 3 views
7

В следующем экземпляре Монады:Trouble Понимание Монада (->)

instance Monad ((->) r) where 
    return = const 
    f >>= k = \ r -> k (f r) r 

Это заставляет k быть функцией двух параметров? И если да, то зачем вы хотите пройти (f r) И r до k?

+0

Вам может понравиться раздел [Monads as Containers] (https://wiki.haskell.org/Monads_as_containers) на монаде читателя (поиск «читателя»). –

+0

Да 'k' - это функция' a -> r -> b'. 'r' - единственный экземпляр' r', и 'f r' - единственный способ получить' a', поэтому у вас нет выбора. – Lee

+0

Возможный дубликат [Как использовать (->) экземпляры Monad и путаницу о (->)] (http://stackoverflow.com/questions/5310203/how-to-use-instances-of-monad-and- путаница, о) – Cactus

ответ

9

Является ли это принуждением k функцией двух параметров?

Да. Глядя на определение Monad, мы имеем

class Monad m where 
    return :: a -> m a 
    (>>=) :: m a -> (a -> m b) -> m b 

Подставив (->) r для m, мы имеем

return :: a -> (->) r a 
(>>=) :: (->) r a -> (a -> (->) r b) -> (->) r b 

Теперь (->) r a просто странный синтаксис r -> a, а так же для других случаев, поэтому мы get

return :: a -> r -> a 
(>>=) :: (r -> a) -> (a -> r -> b) -> r -> b 

Итак, мы можем видеть, что действительно второй аргумент >>= должен быть функцией (по крайней мере) двух аргументов.

Почему? Поскольку функция двух аргументов - это просто функция, принимающая один аргумент и возвращающая функцию одного аргумента, тогда как второй аргумент >>= должен быть функцией, принимающей один аргумент и возвращающей значение конструктора типа монады; для функции monad это значение будет функцией. Следовательно, второй аргумент >>= будет функцией двух аргументов.

[W] hy вы бы хотели (f r) AND r to k?

Отчасти потому, что это делает тип (->) r подходящей однородной структурой Монады, что полезно по многим причинам.

Отчасти k не знает, какую функцию использовать f. Это означает, что с точки зрения k два аргумента f r и r действительно независимы --- k не может рассчитать один от другого.

Рассмотрим эту функцию:

-- | 'f' takes two numbers and adds them together 
f :: (->) (Int, Int) Int 
f = fst >>= \ n0 -> snd >>= \ n1 -> return (n0 + n1) 

Функция \ n0 -> snd >>= \ n1 -> return (n0 + n1) не заботится, где ее аргумент исходит из, или, в частности, что ее аргумент является первым компонентом ввода. Таким образом, для этого необходимо как аргумент n0, так и полный ввод.

Смежные вопросы