在 Purescript 中提示 Monad

Prompt Monad in Purescript

我正在研究 Prompt 的定义及其描述的 Bind 实例 here 并试图弄清楚它在 Purescript 中的外观。

我正在使用 Purescript.Exists 作为存在类型。那么我的定义是:

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 = ???

我坚持在 Bind 实例中编写 Ask 案例,尤其是在使用 runExists 时,我对类型非常困惑。

这个实例应该怎么写?

谢谢,

迈克尔

像这样应该可以解决问题:

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.