如何编写一个从集合中减去效果的purescript效果处理程序

mjk*_*aye 6 purescript

PureScript by Example,在Eff Monad - > Handlers and Actions一节中声明"[一个效果]处理程序通常从集合中减去效果".但是,这些示例相当不透明,我无法弄清楚如何编写自己的处理程序来实现这一点.

具体来说,我正在使用purescript-aff和purescript-affjax.我想将runAff(来自purescript-aff)与get(来自purescript-affjax)结合使用.

问题是get使用Affjax monad,而runAff期望使用Aff monad.

Affjax定义为:

type Affjax e a = Aff (ajax :: AJAX | e) (AffjaxResponse a)
Run Code Online (Sandbox Code Playgroud)

Aff定义为:

foreign import data Aff :: # ! -> * -> *
Run Code Online (Sandbox Code Playgroud)

因此,我想编写一个具有以下类型的函数:

Affjax e a -> Aff e a
Run Code Online (Sandbox Code Playgroud)

在我看来,这需要一个减去ajax效果集部分的处理程序.如何编写这样的处理程序?

尝试进行模式匹配,如下所示,当然会导致错误unexpected |.

handleAffjax :: Affjax e a -> Aff e a
handleAffjax (Aff ( | eff1 ) resp1) = Aff eff1 resp1
Run Code Online (Sandbox Code Playgroud)

谢谢大家.

更新

@ christoph-hegemann在下面的回答的启发,我能够用我的代码追踪大部分问题.

我认为标题中的问题的答案是,不会从集合中减去效果,并且该描述有点令人困惑.处理后效果仍然存在.

我缺少的直觉是我必须将预期的效果添加到调用函数类型.在main某种程度上缺乏关于隐藏的类型声明.当我将Christoph的例子变成下面的编译示例时,我解决了这个问题:

module Main where

import Debug.Trace
import Network.HTTP.Affjax
import Control.Monad.Aff
import Control.Monad.Eff
import Control.Monad.Eff.Exception

initialUrl :: URL
initialUrl = "http://127.0.0.1:8000/api/v1/navitem/2/"

runGet :: forall e. Eff (ajax :: AJAX, trace :: Trace | e) Unit
runGet = runAff errorHandler successHandler (get initialUrl)

errorHandler :: forall e. Error -> Eff (trace :: Trace | e) Unit
errorHandler err = print err

successHandler :: forall e. AffjaxResponse String -> Eff (trace :: Trace | e) Unit
successHandler res = print res.response

main = runGet
Run Code Online (Sandbox Code Playgroud)

Chr*_*ann 5

我会一步一步地采取它^^

问题是get使用Affjax monad,而runAff期望使用Aff monad.

Affjax定义为:

type Affjax e a = Aff (ajax :: AJAX | e) (AffjaxResponse a)

Affjax是一种类型的同义词.这意味着Affjax不是它自己的Monad,而是Aff Monad的特例.我们来看看下一个:

Aff定义为:

foreign import data Aff :: # ! -> * -> *

所以Aff是一个类型构造函数,它将2个Type作为Arguments来生成一个新类型.该类型的第一个参数是#!告诉我们:

  • # - >这是一排......
  • ! - > ......由效果组成

因此,当您查看Affjax类型同义词的定义时,您可以看到Aff类型构造函数的第一个参数是一行效果,其中包含ajax :: Ajax效果但是对于扩展是开放的| e.

Aff的第二个参数只是一种类型,在Affjax的情况下,由类型变量a参数化的AffjaxResponse.

查看Pursuit会发现AffjaxResponse只是记录的类型同义词,因此您可以使用点运算符访问其成员.

我已经整理了一个最小的编译示例,它可以帮助您入门:

module Main where

import Debug.Trace
import Network.HTTP.Affjax
import Control.Monad.Aff
import Control.Monad.Eff
import Control.Monad.Eff.Exception

errorHandler :: forall e. Error -> Eff (trace :: Trace | e) Unit
errorHandler err = print err

successHandler :: forall e. AffjaxResponse String -> Eff (trace :: Trace | e) Unit
successHandler res = print res.response

main = runAff errorHandler successHandler (get "http://www.myApi.com/api" )
Run Code Online (Sandbox Code Playgroud)