请确认或更正我对此Haskell代码段的“英语解释”

时间:2009-04-22 04:48:42

标签: c# haskell types f# algebraic-data-types

8 个答案:

答案 0 :(得分:8)

答案 1 :(得分:4)

类比通常缺乏各种各样的方式,但既然你知道C#我认为这可能会有所帮助。

这就是我在C#中描述List a定义的方法,也许这会清除一些事情(或者更可能让你更加困惑)。

class List<A>
{
}

class Nil<A> : List<A>
{
    public Nil() {}
}

class Cons<A> : List<A>
{
    public A Head;
    public List<A> Tail;

    public Cons(A head, List<A> tail)
    {
        this.Head = head;
        this.Tail = tail;
    }
}

如你所见;

  • List类型有一个类型参数(<A>),
  • Nil构造函数没有任何参数,
  • 并且Cons构造函数有两个参数,类型为head的值为A,类型为tail的值为List<A>

现在,在Haskell中,NilCons只是List a数据类型的构造函数,在C#中它们本身也是类型,所以这就是类比失败的地方。

但是我希望这能让你直观地了解不同的A代表什么。

(并且请评论这种可怕的比较如何不公正Haskell的数据类型。)

答案 2 :(得分:3)

Cons a (List a)

Cons的第一个字段是“a”类型的值。第二个是类型为“List a”的值,即使用与当前列表的参数相同类型参数化的List。

答案 3 :(得分:3)

5是错误的,我会说如下6替换两者:

缺点{1} a {2}(列表a){3}是一个名为Cons({1}之前的部分)的构造函数,用于需要两个值的类型List a(数据List a part)的值:类型a({1}和{2}之间的部分)和类型列表a之一({2}和{3}之间的部分)。

为了帮助您解决明显的混淆:在Haskell中,您几乎不必提供显式类型参数 - 类型推断从您的值中推断出类型。所以从某种意义上说,当你将值传递给函数或构造函数时,你也可以指定一个类型,即。传入值的类型。

答案 4 :(得分:3)

是的,数据语法有点令人困惑,因为它包含了名称和类型,并没有真正区分它们之间的语法。特别是在构造函数定义中:

Cons a (List a)

第一个单词是构造函数的名称;每个其他单词都是某些预先声明的类型的名称。因此,aList a已经在范围内(a已被“a”中的data List a带入范围,您就是说这些是参数的类型。通过使用记录语法来说明相同的事情,可以更好地证明他们的角色:

Cons { headL :: a, tailL :: List a }

即。类型为List Int的值,如果是使用Cons构造函数构建的,则有两个字段:IntList Int。如果它是用Nil构造的,则它没有字段。

答案 5 :(得分:2)

  

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

     

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

不,它确定第二个字段的值为Nil。根据您的定义,NilList a类型的值。因此Cons 0 Nil也是如此。在Cons 1 it中,第二个字段的值为it;即Cons 0 Nil。这正是REPL所展示的: Cons 1 (Cons 0 Nil)

答案 6 :(得分:1)

我看了你编辑过的问题。

  

当我使用Cons创建实例时   值构造函数,那些实例   “解释”第一个'a'作为意义   “把价值放在这里。

在“缺点(列表a)”中,“a”和“列表a”都是类型。我不明白它的“价值”是什么。

  

当我输入“Cons 0 Nil”时,它会使用   “Cons”值构造函数创建一个   列表的实例。它从0开始学习   type参数是“Integer”。   到目前为止,没有混乱。

     

然而,它也决定了   缺点的第一个字段的值   是0.但它没有任何决定   第二个字段的价值......它   只确定第二个字段   有一种“List Integer”。

第二个字段的值为Nil

  

所以我的问题是,为什么“a”在   第一个字段意思是“这个类型   字段是'a'和它的值   字段是'a'“,而”a“在第二个字段中   字段仅表示“此类型   字段是'列表'?“

第一个字段中的“a”表示“此字段的类型为'a'”。第二个字段中的“列表a”表示“此字段的类型为'列表a'”。在上面的“缺点0”的情况下,“a”被推断为“整数”。因此“Cons a(List a)”变为“Cons Integer(List Integer)”。 0是Integer类型的值。 Nil是“List Integer”类型的值。

  

此字段的值为“a”

我不明白你的意思。 'a'是一个类型变量;它与价值观有什么关系?

答案 7 :(得分:0)

只是为了给你一些额外的“帮助”,万一你还在看这个帖子。 Haskell有一些约定会弄乱别人关于事情应该如何完成的想法 - 在Haskell中,参数化类型是如此普遍接受的,它通常被认为是一个类型级函数。同样,值构造函数被认为是“特殊”函数,它们也允许模式匹配,除了它们“取值(或更多)并产生值作为结果”。

Haskell的另一个“有趣”特征是它没有显式(或隐式)评估函数的参数,即使该参数在括号中。让我稍微说一点:Haskell函数不会在其他参数之前评估括号中的参数。参数放在括号中仅用于分组目的,而不是“首先”评估它们。 Haskell为一个函数赋予(“apply”)一个比任何其他操作更高优先级的参数 - 甚至高于它自己的一个参数的隐式函数应用程序。这就是为什么Cons构造函数在第二个参数(List a)周围有parens - 告诉编译器Cons有两个参数,而不是三个。括号仅用于分组,而不是优先级!

作为一个侧面话题,请注意F#中的类型。由于F#的根源是ML,因此其参数化类型的参数位于前面 - int list,而不是(List Int)! Haskell以另一种方式做到了,因为它与Haskell的功能相同 - 首先是函数,然后是函数的参数。这鼓励了一个共同使用模式,并解释了为什么Haskell类型和值构造函数是大写的 - 提醒您正在处理类型/类相关的事情。

好的,我已经完成了;谢谢你让我把这个巨大的Wall O'Text放在你的财产上......