首页 > 解决方案 > 检查 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 - 打印我的命令Message有效负载中的内容。test

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

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

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

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

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

msg必须是自定义类型吗?

标签: typescommandmessageelmread-eval-print-loop

解决方案


msg必须是自定义类型吗?

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

现在回到问题的核心:在 REPL 中,您可以评估 Elm表达式——而 Elm 本身是一种语言,这意味着它(几乎)不能执行任何效果,例如 HTTP 请求。

但是,Elm 中有一种特殊的值称为 a Cmd,如果将其传递给该Program值,它将要求运行时代表您执行一些效果。为此,您必须Program通过命名来指定您的应用程序入口点的值main

这不能在 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 - 打印我的测试命令的消息有效负载中的内容。

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

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

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

推荐阅读