gpt4 book ai didi

types - 理解这个 elm url-parser Parser 类型声明

转载 作者:行者123 更新时间:2023-12-04 06:05:15 30 4
gpt4 key购买 nike

试图理解 evancz/url-parser 模块时,我偶然发现了这种我难以理解的类型声明:( source )

type Parser a b =
Parser (State a -> List (State b))

“解析器”作为类型名称出现在类型定义中这一事实尤其令人不安。

有人可以用英语造句解释类型注释吗?
例如“给定两个抽象类型 a 和 b,...?”

非常感谢。

最佳答案

这里有一些东西需要解压,所以让我们分解一下:

类型名称可以具有相同名称的构造函数。这是有效的代码:

type Foo a = Foo a

上面的 Foo 类型接受一个类型参数,并且有一种创建类型为 Foo a 的值的方法。 ,通过使用其恰好共享相同名称的单个构造函数。这让我们可以定义不同类型的 Foos,如下所示:

fooString : Foo String
fooString = Foo "abc"

fooInt : Foo Int
fooInt = Foo 123

在上面的例子中, Foo充当字符串或 int 值的容器。但这并不是它可以坚持的全部。由于函数是 Elm 中的值,因此您可以使用 Foo保留一个功能。让我们定义一个函数,它接受一个整数并将其加一:

plusOne : Int -> Int
plusOne = (+) 1

现在,让我们把它放在 Foo 中。值(value):

fooPlusOner : Foo (Int -> Int)
fooPlusOner = Foo plusOne

这是完全有效的代码。 Foo (Int -> Int) 类型的值只是一个函数的包装器。所以现在我们包装了一个函数,我们怎么能用它做点什么呢?让我们创建一个在 fooPlusOner 中运行函数的函数。 ,给出一个整数作为起点:

runFooIntFunc : Int -> Foo (Int -> Int) -> Int
runFooIntFunc val (Foo f) = f val

如果你像这样运行这个函数 runFooIntFunc 3 fooPlusOner ,您收到值 4 .

我们可以稍微概括一下这个函数,以摆脱显式使用 Ints:

runFooFunc : a -> Foo (a -> a) -> a
runFooFunc val (Foo f) = f val

现在,这将适用于任何返回与其输入相同类型的函数。假设我们想要一个 Foo 函数,它为任何字符串添加一个感叹号:

fooShouter : Foo (String -> String)
fooShouter = Foo (\s -> s ++ "!")

运行 runFooFunc "wow" fooShouter将返回 "wow!" .

现在,让我们分解解析器定义中发生的事情:

type Parser a b =
Parser (State a -> List (State b))

注意 Parser构造函数只是简单地包装了一个 State a -> List (State b) 类型的函数.不幸的是, State type 是不透明的(非导出的),因此我们不能直接针对它编写代码,但您可以定义自己的状态并使用它。

无需过多介绍实现细节,请记住它只是某种类型函数的包装器。所以问题可能是,为什么要这样写?

好吧,该实现使得在 Parsers 上以隐藏实现细节的方式分层 Parsers 变得更加容易,提供了原始解析器的良好基础,允许以优雅的方式分层解析器而不必担心状态。在处理解析器和解码器或任何围绕状态的东西时,这种类型的模式经常出现在函数式语言中。

通读 State monad 的介绍可能会有所帮助。在 haskell 里面。类型不同,但许多基本概念是共享的。

关于types - 理解这个 elm url-parser Parser 类型声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46428129/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com