gpt4 book ai didi

c# - 请确认或更正我的这个 Haskell 代码片段的 "English interpretation"

转载 作者:可可西里 更新时间:2023-11-01 08:04:59 26 4
gpt4 key购买 nike

我是一名 C# 开发人员,正在通过 "Real World Haskell" 工作为了真正理解函数式编程,所以当我学习 F# 时,我会真正理解它,而不仅仅是“在 F# 中编写 C# 代码”,可以这么说。

好吧,今天我遇到了一个我以为我理解了 3 次不同的例子,然后才看到我错过的东西,更新我的解释,然后递归(还有诅咒,相信我)。

现在我相信我确实理解了它,我在下面写了一个详细的“英文解释”。 Haskell 大师能否确认这种理解,或者指出我遗漏了什么?

注意:Haskell 代码片段(直接从书中引用)定义了一个自定义类型,该类型旨在与内置的 Haskell 列表类型同构。

Haskell 代码片段

data List a = Cons a (List a)
| Nil
defining Show

编辑:经过一些回复后,我看到了一个误解,但我不太清楚可以纠正该错误的 Haskell“解析”规则。所以我在下面包含了我原来的(不正确的)解释,然后是更正,然后是我仍然不清楚的问题。

编辑:这是我对片段 的原始(不正确)“英文解释”
  • 我正在定义一个名为“List”的类型。
  • List 类型是参数化的。它只有一个类型参数。
  • 有 2 个值构造函数可用于创建 List 的实例。一个值构造函数称为“Nil”,另一个值构造函数称为“Cons”。
  • 如果您使用“Nil”值构造函数,则没有字段。
  • “Cons”值构造函数只有一个类型参数。
  • 如果您使用“Cons”值构造函数,则必须提供 2 个字段。第一个必填字段是 List 的一个实例。第二个必填字段是 a 的一个实例。
  • (我故意省略了关于“定义表演”的任何内容,因为它不是我现在想要关注的部分)。

  • 更正后的解释如下(粗体更改)
  • 我正在定义一个名为“List”的类型。
  • List 类型是参数化的。它
    有一个类型参数。
  • 有2个值构造函数
    可用于制作实例
    名单。一个值构造函数是
    称为“Nil”和另一个值
    构造函数称为“缺点”。
  • 如果您使用“Nil”值构造函数,则没有字段。

    5.(此行已被删除……这是不准确的)“Cons”值构造函数只有一个类型参数。
  • 如果使用“Cons”值构造函数,则有 2 个字段
    必须提供。首先
    必填字段是 a 的一个实例。
    第二个必填字段是
    “List-of-a”的实例。
  • (我故意省略了关于“定义表演”的任何内容,因为它不是我现在想要关注的部分)。

  • 还不清楚的问题

    最初的困惑是关于“Cons a (List a)”的片段部分。事实上,这是我仍然不清楚的部分。

    人们已经指出,“Cons”标记之后的每一行都是一个类型,而不是一个值。所以这意味着这一行说“Cons 值构造函数有 2 个字段:一个是 'a' 类型,另一个是 'list-of-a' 类型。”

    了解这一点非常有帮助。然而,有些事情还不清楚。当我使用 Cons 值构造函数创建实例时,这些实例“解释”第一个 'a' 的意思是“将传入的值放在此处”。但是他们不会以相同的方式解释第二个“a”。

    例如,考虑这个 GHCI session :
    *Main> Cons 0 Nil
    Cons 0 Nil
    *Main> Cons 1 it
    Cons 1 (Cons 0 Nil)
    *Main>

    当我键入“Cons 0 Nil”时,它使用“Cons”值构造函数来创建 List 的实例。从 0 开始,它得知类型参数是“Integer”。到目前为止,没有混淆。

    但是,它也确定了 Cons 的第一个字段的值是 0。但它没有确定第二个字段的值……它只确定第二个字段的类型为“List Integer”。

    所以我的问题是,为什么第一个字段中的“a”表示“该字段的类型是 'a',该字段的值是 'a'”,而第二个字段中的“a”仅表示“类型”这个字段是'List of a'”?

    编辑:我相信我现在已经看到了曙光,多亏了一些回应。让我在这里说明一下。 (如果不知何故它在某些方面仍然不正确,请务必让我知道!)

    在代码片段“Cons a (List a)”中,我们说“Cons”值构造函数有两个字段,第一个字段的类型为“a”,第二个字段的类型为“List of a” '。

    这就是我们要说的! 特别是,我们对值(value)观一无所知!这是我遗漏的一个关键点。

    稍后,我们要创建一个实例,使用“Cons”值构造函数。我们在解释器中输入:“Cons 0 Nil”。此 明确告诉 Cons 值构造函数使用 0 作为第一个字段的值,并使用 Nil 作为第二个字段的值。

    这就是全部。一旦您知道值构造函数定义只指定类型,一切就变得清晰了。

    感谢大家的有用回复。正如我所说,如果仍有任何问题,请务必告诉我。谢谢。

    最佳答案

    • The "Cons" value constructor has a single type parameter.


    不:您在声明 data List a 时已经对其进行了参数化。 .一个有效的属性是,如果我有一个 Nil::List Int,我不能将它与 Nil::List Char 互换。

    • If you use the "Cons" value constructor, there are 2 fields which must be provided. The first required field is an instance of List. The second required field is an instance of a.


    你已经把它交换了:第一个必填字段是 a 的实例,第二个字段是 List 的实例。

    This chapter of Real World Haskell可能会感兴趣。

    Thanks. That is the chapter I'm on right now. So ... when the code says "Cons a (List a)", I thought the "Cons a" part of that was stating that the Cons value constructor was parameterised. They haven't yet covered the syntax for parameterised types, so I guessed that the syntax must require re-stating "a" if you intend to use a. But you're saying that's not necessary? And therefore that's not what that "a" means?



    不。一旦我们在我们的类型中声明了一个参数,我们就可以重用它,否则说“应该在那里使用那个类型”。有点像 a -> b -> a类型签名: a 正在参数化类型,但是我必须使用相同的 a 作为返回值。

    OK, but this is confusing. It seems that the first "a" means "the first field is an instance of a",



    不,那不是真的。它只是意味着数据类型参数化了某种类型 a。

    and it ALSO means "the first field has the same value as the value they passed in for a". In other words, it specifies type AND value.



    不,这也不是真的。

    这是一个很有启发性的例子,你可能见过也可能没见过它的语法:

    foo::Num a => a -> a

    对于一个函数来说,这是一个相当标准的签名,它接受一个数字并对它做一些事情并给你另一个数字。不过,在 Haskell 中,我所说的“数字”实际上是一些实现“Num”类的任意类型“a”。

    因此,这解析为英语:

    Let a indicate a type implementing the Num typeclass, then the signature of this method is one parameter with the type a, and the return value of the type a



    类似的事情发生在数据上。

    我还发现 Cons 规范中的 List 实例也让您感到困惑:解析时要非常小心:而 Cons 指定了一个构造函数,它基本上是 Haskell 要将数据包装到的一种模式,(列表 a) 看起来像一个构造函数,但实际上只是一个类型,如 Int 或 Double。 a 是一种类型,不是该术语任何意义上的值。

    编辑:回应最近的编辑。

    我认为首先需要进行解剖。然后我会逐条处理你的问题。

    Haskell 数据构造函数有点奇怪,因为你定义了构造函数签名,而不必做任何其他脚手架。 Haskell 中的数据类型没有任何成员变量的概念。 (注意:有一种替代语法更适合这种思维方式,但我们现在先忽略它)。

    另一件事是 Haskell 代码很密集;它的类型签名就像那样。所以希望看到在不同的上下文中重复使用相同的符号。类型推断在这里也发挥着重要作用。

    所以,回到你的类型:

    数据列表 a = 缺点 a(列表 a)
    |零

    我把它分成几部分:

    数据列表a

    这定义了类型的名称,以及它稍后将拥有的任何参数化类型。请注意,您只会看到它出现在其他类型签名中。

    缺点a(列表a)|


    这是数据构造函数的名称。这不是一种类型。但是,我们可以对其进行模式匹配,ala:

    foo::列出一个 -> Bool
    foo 无 = 真

    注意 List a 是签名中的类型,而 Nil 既是数据构造函数,也是我们模式匹配的“事物”。

    缺点a(列表a)

    这些是我们插入构造函数的值的类型。 Cons 有两个条目,一个是 a 类型,一个是 List a 类型。

    So my question is, why does "a" in the first field mean "the type of this field is 'a' and the value of this field is 'a'", while "a" in the second field means only "the type of this field is 'List of a'"?



    简单:不要把它当作我们指定类型;想想它有 Haskell 正在推断它的类型。因此,出于我们的意图和目的,我们只是在其中粘贴 0,在第二部分粘贴 Nil。然后,Haskell 查看我们的代码并思考:
  • 嗯,我想知道 Cons 0 Nil 的类型是什么
  • 好吧, Cons 是 List a 的数据构造函数。我想知道 List a 的类型是什么
  • 嗯,a 用在第一个参数中,所以因为第一个参数是一个 Int(另一种简化;0 实际上是一个奇怪的东西,被归类为 Num),所以这意味着 a 是一个 Num
  • 嘿,好吧,这也意味着 Nil 的类型是 List Int,尽管实际上没有任何内容可以说

  • (注意,这实际上并不是它的实现方式。Haskell 在推断类型时可以做很多奇怪的事情,这就是错误消息很糟糕的部分原因。)

    关于c# - 请确认或更正我的这个 Haskell 代码片段的 "English interpretation",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/775730/

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