Как `get` работает в версии CPS монады State?

Я пытаюсь понять продолжение в целом, следуя этому руководству.

Однако мне трудно понять следующий пример в разделе 2.10:

# let get () =
    shift (fun k -> fun state -> k state state) ;;
get : unit => ’a = <fun>

state относится к типу int, я полагаю. Чего я не понимаю, так это типа k. Насколько я понимаю, k захватывает все вычисления, следующие за get (), и, поскольку мы говорим о монаде состояния, k разумно представлять вычисление, которое будет продолжено с помощью int, следовательно

k : int => 'a

но, судя по коду, этого не происходит, и требуется state во второй раз, что на самом деле означает:

k : int => int => 'a

но я не понимаю, откуда берется второй, и в каком смысле get относится к типу unit => 'a вместо unit => int => 'a?

По сравнению с реальной реализацией монады состояния путаница добавляет больше:

newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }

то есть переход состояния представлен как функция от состояния к кортежу результата и состояния, что соответствует моему первому пониманию.

Кто-нибудь может дать наводку?

Во-вторых, как мне реализовать get здесь, используя Haskell Control.Monad.Trans.Cont? У меня проблемы с утешением системы типов.


ОБНОВИТЬ

Кажется, я получил второй:

Prelude Control.Monad.Trans.Cont> let get () = shift $ \k -> return $ \i -> k i i

Но я все еще не понимаю, почему мне нужно дважды применять состояние к продолжению.


person Jason Hu    schedule 14.06.2017    source источник
comment
@Bergi это на самом деле называется OchaCaml. Я следую руководству, но не думаю, что используемые языки влияют на понимание концепции в данном случае.   -  person Jason Hu    schedule 15.06.2017


Ответы (1)


Вы применяете k к state дважды, потому что первый соответствует результату get () (мы хотим, чтобы эффект get извлекал текущее состояние и возвращал его как результат), а второй соответствует передаче состояния после get (что, поскольку get не изменяет состояние, это то же самое, что и состояние перед get) до следующего вычисления с сохранением состояния.

Другими словами, поскольку монада состояния State s a ~ s -> (a, s), ее CPS-версия State s r a ~ s -> (a -> s -> r) -> r, и поэтому для get : State s s, поскольку a ~ s, продолжением будет функция типа s -> s -> r.

person Cactus    schedule 15.06.2017
comment
это основная часть, которую я не понимаю. должно ли быть достаточно продолжения, просто передав текущее состояние? я также не понимаю, как перейти от версии государственной монады к версии cps. - person Jason Hu; 15.06.2017
comment
также как я могу узнать тип продолжения, просто взглянув на код? какую часть смотреть, дырку или не дырку? - person Jason Hu; 15.06.2017
comment
Подумайте, что бы вы хотели передать, если бы результатом get должно было быть текущее состояние + 1 (фиксация его на State Int для примера). Последующее состояние будет таким же, как входящее состояние, но результат будет другим. Таким образом, вам нужно передать state + 1 в качестве аргумента результата и state в качестве аргумента нового состояния для продолжения. - person Cactus; 15.06.2017