在 Elm 中检查变量

Inspecting variables in Elm

我正在尝试了解 Elm 类型系统的工作原理。来自命令式编程背景,我习惯于利用带有步骤和断点的调试器来弄清楚发生了什么。但显然这不是功能方式。

使用 REPL 找出简单的例子很容易,但是使用 Http.get 之类的例子会变得更加复杂。

这是我尝试过的方法:

显然,当 HTTP 请求完成时,我必须为要由运行时返回的消息定义特定的自定义类型:

> type Message = Done (Result Http.Error String)

现在我将 Http.get 的结果存储在某个变量中:

> test = Http.get { url = "http://192.168.1.10:3000/site", expect = Http.expectString Done }

那我想看看里面有什么test :

> test
<internals> : Cmd Message

如果我理解正确,test 似乎具有预期的类型,现在是一些我可以以某种方式发送到 Elm 运行时的命令。

现在我要做的是:

1 - 打印我的 test 命令的 Message 负载中的内容。

2 - 将命令发送到运行时并以某种方式获取结果(从 REPL)

3 - 打印 Message 我应该从运行时返回的内容。

可能吗?是否有意义 ? 如果不是,我应该如何了解表面魔法背后发生的事情才能真正理解 Elm,尤其是相当神秘的类型注释?

奖金问题: Http.get 具有以下定义:

get :
    { url : String
    , expect : Expect msg
    }
    -> Cmd msg

msg 必须是自定义类型吗?

Do msg have to be a custom type ?

没有。它可以是任何类型,例如也可以是 String

现在进入问题的核心:在 REPL 中,您可以计算 Elm expressions - 而 Elm 本身就是一个 pure语言,这意味着它不能执行(几乎)任何效果,例如 HTTP 请求。

然而,在 Elm 中有一种特殊的值叫做 Cmd,如果交给 Program 值会要求 运行time 执行一些效果代表你。为此,您必须通过将其命名为 main.

来指定 Program 值您的应用程序入口点

这在 REPL 中是做不到的;因此 Elm REPL 无法执行 Cmds.


因此,为了使用 Cmd,您需要创建一个 Elm 应用程序并 运行 它在浏览器中。

像这样:

import Browser 
import Html


main = Browser.element   
    { init = \() -> ({}, test) -- ask the runtime for your message
    , update = update
    , subscriptions = \_ -> Sub.none 
    , view = \_ -> Html.text "Hello world!"
    }

update msg model =
    case msg of
        Done result ->
            let 
                _ = Debug.log "HTTP request completed" result

            in
            ( model, Cmd.none )

1 - print what's inside the Message payload of my test command.

您的 test 命令没有要打印的消息负载。类型参数 Cmd Message 并不意味着该值以某种方式“包含” Message 类型,它只是断言类型之间存在某种关系。在这种情况下,未来关系,您可以将其视为“将来可能产生 Message 类型值的命令”。

你可以想到 Cmd 类型实现了这样的东西(不是,但可能是):

type Cmd msg
    = NoCmd
    | HTTP Method Url (Response -> msg)
    | Sleep Duration (() -> msg)
    ...