《Real World Haskell》笔记(2):类型与函数

2018-12-08  本文已影响0人  Mexplochin
Haskell类型系统

静态、强类型检查使得 Haskell 更安全,而类型推导则让它更精炼、简洁。正是自动推导帮助 Haskell 程序既可以获得静态类型带来的所有好处,而又不必像传统的静态类型语言那样,忙于添加各种各样的类型签名(如 C 语言的函数原型声明)

强类型系统使Haskell拒绝执行任何无意义的表达式,并且不会自动地将值从一个类型转换到另一个类型;静态类型系统则使Haskell编译器可以在编译期(而不是执行期)知道每个值和表达式的类型;Haskell类型可以通过自动推导得出。

类型签名

类型签名(v.) 即为表达式显式的指明类型
输入var::T,向解释器或编译器表明var的类型是T。显示签名必须正确,否则 Haskell 编译器就会产生错误;若未显式签名,则类型由自动推导决定。

一些基本类型

Char单个Unicode字符
Bool表示一个布尔逻辑值,该类型只有两个值: True 和 False
Int带符号的定长整数
Integer带符号的非定长整数
Double浮点数

复合数据类型

列表 [a]
性质:类型多态(polymorphic)列表元素的值可以是任意类型(但所有元素必须同种类型)
方法:

元组
性质:元组的类型由它所包含元素的数量、位置和类型决定(如果两个元组里都包含着同样类型的元素,而这些元素的摆放位置不同,那么它们的类型就不相等)
方法:

调用函数

compare (sqrt 3) (sqrt 6)

传表达式给函数

Haskell 的函数应用是左关联的。比如说,表达式 a b c d 等同于 (((a b) c) d),要将一个表达式用作另一个表达式的参数,那么就必须显式地使用括号来包围它,若移走括号,那么编译器就会认为我们试图将多个参数传给函数。

函数类型

lines::String->[String]
String -> [String] 的实际意思是指 lines 函数定义了一个从 String 到 [String] 的函数映射。
理解为,lines 函数接受一个字符串作为输入,并将这个字符串按行转义符号(换行符)分割成多个字符串后返回字符串列表。所以,函数的类型签名可以提示函数自身的功能。

多参数函数的类型

take::Int->[a]->[a]
类型签名中的 -> 符号是右关联的:Haskell 从右到左地串联起这些箭头,使用括号可以清晰地标示即take::Int->([a]->[a])

条件求值:if表达式
--file myDrop.hs
myDrop n xs = if n<=0 || null xs
  then xs
  else myDrop (n-1) (tail xs)
多态

当需要编写带有多态类型的代码时,需要使用类型变量。这些类型变量以小写字母开头,作为一个占位符,最终被一个具体的类型替换。
如,[a] 用一个方括号包围一个类型变量 a ,表示一个“类型为 a 的列表”,当需要一个带有具体类型的列表时,就需要用一个具体的类型去替换类型变量, [Int] 表示一个包含 Int 类型值的列表,它用 Int 类型替换了类型变量 a 。

练习

写一个函数 lastButOne, 返回列表倒数第二个元素

--file lastButOne.hs
lastButOne xs=if length xs==2
  then head xs
  else lastButOne (tail xs)

该函数输入列表长度须大于等于2,否则引发异常Exception: Prelude.tail: empty list,即异常原因是tail函数应用于空列表。

上一篇 下一篇

猜你喜欢

热点阅读