繁体   English   中英

您如何理解 Purescript 中的错误消息?

[英]How do you understand error messages in Purescript?

我正在使用 Purescript 构建一个加密货币套利机器人,主要是为了了解函数式编程范例。 作为主要的 JS 程序员,我发现 Purescript 的错误消息很难解释。 目前,在尝试使用 Affjax 库发出 http 请求时,我遇到了“TypesDoNotUnify”错误。 我的代码如下所示:

import Affjax.ResponseFormat (ResponseFormat(..))
import Affjax.ResponseFormat as ResponseFormat
import Data.Argonaut.Core (Json, fromString, stringify)
import Data.Either (Either(..))
import Data.HTTP.Method (Method(..))
import Effect (Effect)
import Effect.Aff (Aff, launchAff_)
import Effect.Console (log)
import Node.Express.App (App, listenHttp, get)
import Node.Express.Response (send)
import Node.HTTP (Server)
import Node.HTTP.Client (method)

makeQuoteRequest :: String -> String -> String -> String
makeQuoteRequest fromAddress toAddress amount = "https://api.1inch.exchange/v3.0/137/quote?fromTokenAddress=" <> fromAddress <> "&toTokenAddress=" <> toAddress <> "&amount=" <> amount

sendQuoteRequest :: Either Error Unit
sendQuoteRequest = launchAff_ do
  result <- AX.request(AX.defaultRequest {
       url = makeQuoteRequest "0xd6df932a45c0f255f85145f286ea0b292b21c90b" "0xc2132d05d31c914a87c6611c10748aeb04b58e8f" "1000000000000000000"
      ,method = Left GET
      ,responseFormat = ResponseFormat.json
      })
  case result of
    Left err -> log $ "Quote failed: " <> AX.printError err 
    Right response -> log $ "GET /api response: " <> stringify response.body

app :: App
app = do
    get "/" $ send "<a href='http://localhost:8080/quotes'><button>Get Quotes</button></a>"
    get "/quotes" $ send "This is where your quotes should go"

main :: Effect Server
main = do
    listenHttp app 8080 \_ ->
        log $ "Listening on " <> show 8080

VsCode 突出显示以Left err -> log开头的行作为问题的根源,当我 hover 超过该错误时,我得到以下附加信息:

printError:: 错误 → 字符串无法匹配类型

影响

与类型

阿夫

在尝试将类型 Effect Unit 与类型 Aff t0 匹配时同时检查表达式(应用日志)((附加“Quote failed:”)(printError err))在值声明 sendQuoteRequest 中具有类型 Aff t0

其中 t0 是未知类型 PureScript(TypesDoNotUnify)

我希望了解的不仅是如何修复这个错误,而是更多地了解如何解释 Purescript 给我的错误。 如果您的代码中出现此错误,您将采取什么步骤来解决它?

错误消息中的第一句话是:

无法将类型Effect与类型Aff匹配

然后它澄清了一点:

在尝试将类型Effect Unit与类型Aff t0匹配时

这就是绝大多数类型错误的样子。 这意味着编译器一直在跟踪您的程序,找出哪些位具有哪些类型,并最终找到一个位,从一行推理中得出的类型为Effect Unit ,但从另一行推理中得出的类型为Aff t0 (对于一些未知的类型t0 )。 两行推理都是正确的,但它们的结果不匹配,因此编译器不知道下一步该做什么。

你问的那些推理是什么? 好吧,编译器并没有告诉你,这有一个很好的理由:在大多数实际情况下,它对你来说无论如何都没有任何意义。 从编译器的角度来看,推理线中的所有位都同样重要,但是它们太多了,无法一次打印出来,而且它不知道如何选择对您最有意义的位。

但它确实为您提供了另一条有价值的信息——该位结果有两种不匹配的类型:

同时检查表达式(apply log) ((append "Quote failed: ") (printError err))的类型为Aff t0

在这里,我认为编译器可以更好地打印出表达式。 它最终会到达那里,但现在它只需要最小的努力就可以打印出来。 但不要害怕。 我们仍然可以解码它。

看到那边apply了吗? 那是什么? 你没有把它写在你的代码中,那么它是从哪里来的呢?

好吧,您确实在代码中写了它:美元运算符$apply的别名( 请参阅文档)。 同样,运算符<>append的别名。

知道了这一点,我们就可以将这段代码解码成它的原始形式:

(apply log) ((append "Quote failed: ") (printError err))
(($) log) (((<>) "Quote failed: ") (printError err))
($) log ((<>) "Quote failed: " (printError err))
log $ ("Quote failed: " <> (printError err))
log $ "Quote failed: " <> printError err

你看! 这是您在第 25 行写的位!

好的,那么到目前为止我们知道什么? 我们知道编译器已经确定log $...表达式一方面必须具有Effect Unit类型另一方面必须具有Aff t0类型。

让我们看看这段代码是什么。 看:这是从Effect.Console调用log function( 参见文档)。 它的返回类型是Effect Unit 啊哈! 所以就是编译器认为类型应该是Effect Unit的原因! 因为它是调用log函数的结果!

好的,很好,但是Aff t0呢? 好吧,让我们看看该表达式的结果最终会去哪里:作为launchAff_的参数( 请参阅文档)。 launchAff_采用什么类型的参数? 惊喜 - 这是Aff a

所以你 go,谜团解决了: launchAff_需要一个Aff a类型的参数,但你给它一个Effect Unit类型的值。 难怪编译器会抱怨!


至于怎么修。

第一个愚蠢的方法是拨打 go 并搜索 Pursuit。 我们有一个Effect Unit类型的值,我们需要将其转换为Aff a 那可能吗? 好吧,让我们 搜索Effect Unit -> Aff a类型的 function 看哪:有这样一个 function,它叫做liftEffect 所以我们可以使用它:

    Left err -> liftEffect $ log $ "Quote failed: " <> AX.printError err 

繁荣。 完毕。

但是,如果是我,我通常会这样想:我不可能是第一个发生这种情况的人。 想要从Aff上下文中打印到控制台不是很正常吗? 不应该已经有一个应用程序吗?

所以我可能会 go 并搜索合适的类型,例如String -> Aff Unit 看看:实际上有一个log function 适合 它做同样的事情,但它不像你正在使用的那样专门在Effect中工作,而是在任何具有MonadEffect实例的 monad 中工作。 Aff是这样的单子吗? 好吧,让我们搜索Aff查看:是的,是的。 它确实有一个MonadEffect实例。

所以现在,知道了所有这些,我可能只是将导入从Effect.Console (log)更改为Effect.Class.Console (log) ,然后我不需要进行任何其他更改:新log function 将只是在Aff工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM