2016-06-28 3 views
2

Я работаю над определением Prompt и его Bind экземпляром, описанным here, и пытался выяснить, как это будет выглядеть в Purescript.Prompt Monad in Purescript

Я использую Purescript.Exists для экзистенциального типа. Мой Defintion тогда:

data PromptAskF p r a 
    = PromptAskF (p a) (a -> Prompt p r) 

type PromptAsk p r = Exists (PromptAskF p r) 

data Prompt p r 
    = Ask (PromptAsk p r) 
    | Answer r 

instance bindPrompt :: Bind (Prompt p) where 
    bind (Answer x) k = k x 
    bind (Ask ask) k = ??? 

Я застрял на написание Ask дела в случае Bind и, в частности, я очень смущен о типах при работе с runExists.

Как написать этот экземпляр?

Спасибо,

Майкл

ответ

1

Что-то вроде этого следует сделать трюк:

data PromptAskF p r a 
    = PromptAskF (p a) (a -> Prompt p r) 

type PromptAsk p r = Exists (PromptAskF p r) 

mapPA 
    :: forall p r r' 
    . (forall a. (a -> Prompt p r) -> (a -> Prompt p r')) 
    -> PromptAsk p r 
    -> PromptAsk p r' 
mapPA f = runExists \(PromptAskF req cont) -> mkExists $ PromptAskF req (f cont) 

data Prompt p r 
    = Ask (PromptAsk p r) 
    | Answer r 

instance functorPrompt :: Functor (Prompt p) where 
    map f (Answer r) = Answer (f r) 
    map f (Ask ask) = Ask $ mapPA (map (map f)) ask 

instance applyPrompt :: Apply (Prompt p) where 
    apply = ap 

instance applicativePrompt :: Applicative (Prompt p) where 
    pure = Answer 

instance bindPrompt :: Bind (Prompt p) where 
    bind (Answer x) k = k x 
    bind (Ask ask) k = Ask $ mapPA (\cont ans -> cont ans >>= k) ask 

instance monadPrompt :: Monad (Prompt p) 

mapPA функцией является удобством для обновления PromptAskF продолжения без необходимости повторно runExists/mkExists.

+0

Привет, Гэри, спасибо за ваш ответ. Это имеет смысл для меня, но, по-видимому, не для проверки типа! Я получаю следующую ошибку: 'найденная ошибка: в модуле Main в строке 26, столбец 1 - строка 30, столбец 26 Переменная типа сбежала из ее области. в выражении (flip runExists) ask в объявлении значения bindPrompt' –

+0

Я только что обновил ответ, чтобы включить полную реализацию, чтобы убедиться, что на самом деле это typechecks на этот раз! С этим сообщением об ошибке может быть трудно справиться иногда, в этом случае это было вызвано 'flip'ping' runExists', но даже после этого была какая-то странность (не могла помещать лямбду в 'where', без ее возникновения). Перемещение его в 'runPA' делает его немного легче читать, и предоставление явной сигнатуры типа для функции сопоставления помогает избежать других возможных проблем выхода из skolem. –

+0

Удивительный! Спасибо, что нашли время для обновления. Теперь это яснее для меня, чем реализация Haskell, благодаря явным типам ранга-n. –