Поворот A => M [B] в M [A => B]

Для монады M, можно ли превратить A => M[B] в M[A => B]?

Я пробовал следующие типы безрезультатно, что заставляет меня думать, что это невозможно, но я думал, что все равно спрошу. Кроме того, поиск Hoogle для a -> m b -> m (a -> b) ничего не вернул, поэтому я не устраиваю много удачи.

Ответ 1

На практике

Нет, это невозможно сделать, по крайней мере, не в значимом ключе.

Рассмотрим этот код Haskell

action :: Int -> IO String
action n = print n >> getLine

Сначала выполняется n, печатает его (здесь выполняется IO), затем читает строку от пользователя.

Предположим, что мы имели гипотетический transform :: (a -> IO b) -> IO (a -> b). Затем, как мысленный эксперимент, рассмотрите:

action' :: IO (Int -> String)
action' = transform action

Вышеупомянутое должно сделать все IO заранее, прежде чем знать n, а затем вернуть чистую функцию. Это не может быть эквивалентно приведенному выше коду.

Чтобы подчеркнуть эту точку, рассмотрим этот код бессмыслицы ниже:

test :: IO ()
test = do f <- action'
          putStr "enter n"
          n <- readLn
          putStrLn (f n)

Волшебно, action' должен заранее знать, что пользователь будет печатать дальше! Сеанс будет выглядеть как

42     (printed by action')
hello  (typed by the user when getLine runs)
enter n
42     (typed by the user when readLn runs)
hello  (printed by test)

Для этого требуется машина времени, поэтому это невозможно.

В теории

Нет, это невозможно. Аргумент похож на тот, который я дал на аналогичный вопрос.

Предположим противное transform :: forall m a b. Monad m => (a -> m b) -> m (a -> b). Специализируйте m в продолжение monad ((_ -> r) -> r) (я опускаю новую оболочку).

transform :: forall a b r. (a -> (b -> r) -> r) -> ((a -> b) -> r) -> r

Специализировать r=a:

transform :: forall a b. (a -> (b -> a) -> a) -> ((a -> b) -> a) -> a

Применить

transform const :: forall a b. ((a -> b) -> a) -> a

Изоморфизмом Карри-Говарда является интуиционистская тавтология

((A -> B) -> A) -> A

но это Закон Пирса, который не доказуется в интуиционистской логике. Противоречие.

Ответ 2

Другие ответы хорошо иллюстрируют, что вообще невозможно реализовать функцию от a -> m b до m (a -> b) для любой монады m. Однако существуют определенные монады, где вполне возможно реализовать эту функцию. Одним из примеров является монада-читатель:

data Reader r a = R { unR :: r -> a }

commute :: (a -> Reader r b) -> Reader r (a -> b)
commute f = R $ \r a -> unR (f a) r

Ответ 3

Нет.

Например, Option является монадой, но функция (A => Option[B]) => Option[A => B] не имеет значимой реализации:

def transform[A, B](a: A => Option[B]): Option[A => B] = ???

Что вы ставите вместо ???? Some? Some того, что тогда? Или None?