闲话

昨天去了一趟医院,然后就回家休息了,顺便帮着解决一些工作的事,以为小伙伴们应该也会像往前一样十点多十一点那样就撤了,直到今天早晨才知道,他们昨天竟然一直工作到凌晨一点多,太辛苦了,可怜的孩子们,今天我也要一起加班,不知道几点能撤,不过我手上的事倒是做完了,可以写写博客什么的,估计今天晚上会回得比较晚,不知道有没有时间看书。

元组(tuple)

昨天就学了关于元组的一节,元组跟列表有些相似,使用圆括号声明,如(1, "Toby", "M"),通过这个语句已经可以看出其与列表的一些区别,列表中只能保存一种数据类型,而元组可以保存多种不同类型,所以,元组应该更适用于保存一组有意义的档案,每一个元组都可以当做数据表中的一条记录来使用。

那么,如果我们保存的一组数据都是相同的数据类型,比如一组二维坐标点[[1,2], [2,3], 3,4]],这样看起来似乎不会有问题,列表中的每一个列表都是一个坐标,一切都是那么完美,可是一个意外出现了,某位连续加班一个星期的程序猿手一抖,这个就把这个列表写成了[[1,2],[2,3,3],[3,4]],程序正常的完成了编译,于是就把程序放上了线,结果,程序无法按照这些坐标画出期望的线。如果使用元组进行定义会是怎样哪?同个个程序猿又犯了同样的错误,写出来这样一个元组的列表[(1,2),(2,3,3),(3,4)],编译,出了错误提示,编译不通过,然后就直接按照错误提示找到出错的地方。

之所以出现这样的情况是跟Haskell对元组的定义及处理方式分不开的,在Haskell的元组的定义中,元素数量不同的元组,以及相同位置元素的数据类型不同,系统都会认为这些元组是不同的数据类型,于是放在要求所有元素数据类型必须一样的列表中就出了错。

元组内可以由不同数量不同数据类型的元素组成,其中有两个元素组成的元组叫做二元组,由三个元素组成的元组叫做三元组,以此类推,而二元组有一个特别的名字叫序对。

序对有两个专用的函数

  • fst (1, "ONE") 返回序对的第一个元素
  • snd (1, "ONE") 返回序对的第二个元素

另外,还有一个函数可以将两个列表交叉生成一个元组的列表

1
zip [1,2,3,4,5] ["one", "two", "three", "four", "five"]

本例会返回一个元组的列表[(1,"one"),(2,"two"),(3,"three"),(4,"four"),(5,"five")],由于Haskell的惰性,本例还可以写成如下方式

1
zip [1,2..] ["one", "two", "three", "four", "five"]

输出与上例相同。
之所以出现这样的情况是因为,zip执行过程以较短的列表为准,而无限列表与定长的列表相比,当然是定长的列表较短。

找一组三角形吧

要求边长从1到10的直角三角形,首先要明确勾股定理,直角三角形的三条边的边长应该满足a^2 + b^2 = c^2,其中a为底边,c为斜边,b为另一条直角边,a和b都应该小于斜边c,再确定a不短于b,当然有b长于a时的情况,只不过这种情况只是a长于b换了一下摆放方向而已,所以我们可以得出下面的语句。

1
[(a,b,c) | c <- [1..10], a <- [1..c], b <- [1..a], a^2+b^2==c^2]

输出为[(4,3,5),(8,6,10)],当然还可以加一些谓语过滤出更接近需求的组合。

后记

刚才有同事推荐了一个游戏,Core Ball,我费半天劲玩到了第10关,然后就再也玩不下去了,看的眼都花了,然后我就推荐给了王爷,然后王爷成功的玩到了第20关,然后说想吐了,要去躺一会儿,哈哈哈哈。