在 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 无法执行 Cmd
s.
因此,为了使用 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)
...
我正在尝试了解 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 无法执行 Cmd
s.
因此,为了使用 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)
...