types - 检查 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
必须是自定义类型吗?
解决方案
msg
必须是自定义类型吗?
不,它可以是任何类型,例如,也可以是String
例如。
现在回到问题的核心:在 REPL 中,您可以评估 Elm表达式——而 Elm 本身是一种纯语言,这意味着它(几乎)不能执行任何效果,例如 HTTP 请求。
但是,Elm 中有一种特殊的值称为 a Cmd
,如果将其传递给该Program
值,它将要求运行时代表您执行一些效果。为此,您必须Program
通过命名来指定您的应用程序入口点的值main
。
这不能在 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 - 打印我的测试命令的消息有效负载中的内容。
您的test
命令没有要打印的消息有效负载。类型参数Cmd Message
并不意味着值以某种方式“包含”Message
类型,它只是断言类型之间的某种关系。在这种情况下,未来的关系,您可以将其视为“未来可能产生某种Message
价值的命令”。
您可以想到实现的Cmd
类型是这样的(不是,但可能是):
type Cmd msg
= NoCmd
| HTTP Method Url (Response -> msg)
| Sleep Duration (() -> msg)
...
推荐阅读
- c# - 使用不同形式的连接c#
- ruby-on-rails - Rails - 如何在凭证栏上设置过期日期
- c# - Async/Await 链如何工作
- java - Spring autowired 变量不可用
- python - 计算列表中所有大于等于 50 的数字的平均值?
- javascript - 如何让 VS Code 的 Intellisense 与 AngularJS 的注入服务一起工作?
- python - Django:将来自多个文本框的输入组合到单个字段中
- node.js - gcloud app deploy 要求“存储”属性
- c++ - 如何同时接受 std::vector 和 std::initializer_list
- android - 如何创建自定义导航抽屉?