2016-06-28 27 views
2

Promptの定義とそのBindインスタンスについては、hereと記載されており、これがPurescriptでどのように見えるかを調べようとしていました。PurescriptのプロンプトMonad

私は存在タイプとして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 = ??? 

私はrunExistsで作業するとき、特に、私はタイプについて非常に困惑している、BindインスタンスにAskケースを書くことに立ち往生しています。

このインスタンスはどのように記述しますか?

おかげで、トリックを行う必要があり、このような

マイケル

答えて

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機能が繰り返しrunExists/mkExistsにせずにPromptAskF継続を更新するための便利です。

+0

こんにちはゲイリー、あなたの答えに感謝します。これは私には意味がありますが、明らかに型チェッカーには当てはまりません! 'エラーが見つかりました:'エラーが見つかりました: モジュールのメイン の行26、列1-行30、列26 型変数が範囲をエスケープしました。 式の中で(flip runExists) の値の宣言bindPrompt' –

+0

私は実際にこの時間を実際に型チェックするための完全な実装を含めるように答えを更新しました!このエラーメッセージは、時には扱いにくい場合があります。この場合は、 'flip'' runExists'によるものですが、その後も何らかの奇妙なことがあります(ラムダを'どこに ' )。これを 'runPA'に移動することで、読みやすくなります。また、マッピング関数に明示的な型シグネチャを指定することで、他の潜在的なskolemエスケープの問題を避けることができます。 –

+0

恐ろしい!更新する時間をとっていただきありがとうございます。明示的なrank-n型のおかげで、これは現在、Haskellの実装よりも私にとっては明らかです。 –